Can not register variable during parse?
Hey. I wanted to implement a .var macro. In fact, I sat down and wrote a small math algorithm that'd find the key and value for me (which works!). However, when I then try to call register_variable, I get a segfault. Here is what the debugger pointed me to:
* thread #1: tid = 0x584133, 0x0000000100006b6d basic`ucl_parser_register_variable(parser=0x00007fff5fbfdaf0, var=0x00007fff5fbfd8d0, value=0x00007fff5fbfd8c0) + 77 at ucl_parser.c:1834, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
frame #0: 0x0000000100006b6d basic`ucl_parser_register_variable(parser=0x00007fff5fbfdaf0, var=0x00007fff5fbfd8d0, value=0x00007fff5fbfd8c0) + 77 at ucl_parser.c:1834
1831
1832 /* Find whether a variable already exists */
1833 LL_FOREACH (parser->variables, cur) {
-> 1834 if (strcmp (cur->var, var) == 0) {
1835 new = cur;
1836 break;
1837 }
(lldb) bt
* thread #1: tid = 0x584133, 0x0000000100006b6d basic`ucl_parser_register_variable(parser=0x00007fff5fbfdaf0, var=0x00007fff5fbfd8d0, value=0x00007fff5fbfd8c0) + 77 at ucl_parser.c:1834, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
* frame #0: 0x0000000100006b6d basic`ucl_parser_register_variable(parser=0x00007fff5fbfdaf0, var=0x00007fff5fbfd8d0, value=0x00007fff5fbfd8c0) + 77 at ucl_parser.c:1834
frame #1: 0x000000010000143d basic`printer(data=0x000000010020049c, len=8, ud=0x00007fff5fbfdaf0) + 701 at basic.c:66
frame #2: 0x0000000100007c6e basic`ucl_state_machine(parser=0x0000000100200000) + 2654 at ucl_parser.c:1754
frame #3: 0x0000000100006f19 basic`ucl_parser_add_chunk(parser=0x0000000100200000, data=0x0000000100200330, len=374) + 361 at ucl_parser.c:1905
frame #4: 0x00000001000017ff basic`main(argc=1, argv=0x00007fff5fbffb48) + 911 at basic.c:131
The function from which I am calling this:
bool
printer(const unsigned char *data, size_t len, void* ud) {
struct ucl_parser* parser = (struct ucl_parser*)ud;
char key[len];
char value[len];
bool now_value=false;
int left_length;
for(int i=0; i<len; i++) {
if(now_value == false && data[i] != '=') {
// no equal sign, write to key.
key[i]=data[i];
} else if(now_value == false && data[i] == '=') {
// Equal sign. I.e.: key=value
key[i]='\0';
now_value=true;
left_length=i+1; // length starts at 0, but its really above null.
} else if(now_value == false && data[i] == ' ' && data[i+1] == '=') {
// Space and equal. I.e.: key = value
key[i]='\0';
left_length=i+1; // length starts at 0, but its really above null.
i++; // Advance till after the equal sign.
now_value=true;
} else if(now_value == true && data[i] == ' ' && data[i-1] == '=') {
// Space after equal, skip.
continue;
} else if(now_value == true) {
// Value, write to it.
value[( len-(i+(len-i))+(left_length-(len-i)) )]=data[i];
printf("i:%d, di:%c, formular:%d\n", i, data[i], ( len-(i+(len-i))+(left_length-(len-i)) ));
/*printf(
"( %d-(%d+(%d-%d))+(%d-(%d-%d)) )\n",
len, i, len, i, left_length, len, i
);*/
}
}
// Make it NULL terminated.
value[len]='\0';
// print
//printf("VAR: %s=%s\n", key, value);
ucl_parser_register_variable(parser, key, value);
return true;
}
key and value are properly NULL terminated, at least they should be! I see nothing that says different with the printfs. But during variable registration, I get the segfault.
Any soltution?
As far as I see from your backtrace, your struct ucl_parser * pointer has different values:
ucl_state_machine(parser=0x0000000100200000)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
ucl_parser_register_variable(parser=0x00007fff5fbfdaf0, var=0x00007fff5fbfd8d0, ...
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Obviously, it is not correct.
Turns out the way I had passed the parser as user-data was not right. I used &parser - but was supposed to cast it to void* instead. now it works. :)
"Yo Dawg, I heard you like C++, so I added C++ to your build system, so you have to compile before you compile.“ -StackOverflow, Matt Joiner ( http://stackoverflow.com/a/5025525/2423150 )
Am 08.05.2014 um 22:45 schrieb Vsevolod Stakhov [email protected]:
As far as I see from your backtrace, your struct ucl_parser * pointer has different values:
ucl_state_machine(parser=0x0000000100200000) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ucl_parser_register_variable(parser=0x00007fff5fbfdaf0, var=0x00007fff5fbfd8d0, ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Obviously, it is not correct.
— Reply to this email directly or view it on GitHub.
If you use C++, then you always need reinterpret_cast to void * to interact with C. This is the most ugly requirement, but it comes from C not from C++.
Okay, I then just cheated. XD
(void*)parser;
And got no error.
"Yo Dawg, I heard you like C++, so I added C++ to your build system, so you have to compile before you compile.“ -StackOverflow, Matt Joiner ( http://stackoverflow.com/a/5025525/2423150 )
Am 09.05.2014 um 11:30 schrieb Vsevolod Stakhov [email protected]:
If you use C++, then you always need reinterpret_cast to void * to interact with C. This is the most ugly requirement, but it comes from C not from C++.
— Reply to this email directly or view it on GitHub.
C style cast works exactly the same as C++ reinterpret_cast, however, it breaks C++ types interface and auto in particular, hence I'd not recommend to use C style casts in C++.