EXC_BAD_ACCESS in nlrsetjmp.c

C programming, build, interpreter/VM.
Target audience: MicroPython Developers.
Post Reply
p-i-
Posts: 20
Joined: Sun Sep 14, 2014 2:24 pm

EXC_BAD_ACCESS in nlrsetjmp.c

Post by p-i- » Tue Sep 23, 2014 12:13 am

My last post I got µPy to build inside my C++ project.

Now I'm testing it by copying across the following code block from bare-arm's main.c:

Code: Select all

//
//  foo.c
//  JuceDemo
//
//  Created by π on 21/09/2014.
//
//

#include "foo.h"

#include "mpconfig.h"
#include "nlr.h" // <-- port specific nlr_jmp_fail
#include "misc.h"
#include "qstr.h"
#include "lexer.h" // <-- port specific at bottom
#include "obj.h"



void gc_collect(void) {
}

mp_lexer_t *mp_lexer_new_from_file(const char *filename) {
    return NULL;
}

mp_import_stat_t mp_import_stat(const char *path) {
    return MP_IMPORT_STAT_NO_EXIST;
}

mp_obj_t mp_builtin_open(uint n_args, const mp_obj_t *args) {
    return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_open_obj, 1, 2, mp_builtin_open);

void nlr_jump_fail(void *val) {
}

#include <stdint.h>
#include <stdio.h>
#include <string.h>

#include "parse.h"
#include "parsehelper.h"
#include "compile.h"
#include "runtime0.h"
#include "runtime.h"
#include "repl.h"


// - - - - - - -

void do_str(const char *src) {
    mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, src, strlen(src), 0);
    if (lex == NULL) {
        return;
    }
    
    mp_parse_error_kind_t parse_error_kind;
    mp_parse_node_t pn = mp_parse(lex, MP_PARSE_SINGLE_INPUT, &parse_error_kind);
    
    if (pn == MP_PARSE_NODE_NULL) {
        // parse error
        mp_parse_show_exception(lex, parse_error_kind);
        mp_lexer_free(lex);
        return;
    }
    
    // parse okay
    qstr source_name = mp_lexer_source_name(lex);
    mp_lexer_free(lex);
    mp_obj_t module_fun = mp_compile(pn, source_name, MP_EMIT_OPT_NONE, true);
    mp_parse_node_free(pn);
    
    if (module_fun == mp_const_none) {
        // compile error
        return;
    }
    
    nlr_buf_t nlr;
    if (nlr_push(&nlr) == 0) {
        mp_call_function_0(module_fun);
        nlr_pop();
    } else {
        // uncaught exception
        mp_obj_print_exception((mp_obj_t)nlr.ret_val);
    }
}

void test_python()
{
    mp_init();
    do_str("print('hello world!', list(x+1 for x in range(10)), end='eol\n')");
    mp_deinit();
    printf( "done" );
}

From elsewhere in the C++ project I run test_python()

I get a runtime error on line 30 of nlrsetjmp.c:

Code: Select all

#include <setjmp.h>
#include <stdio.h>
#include "mpconfig.h"
#include "nlr.h"

#if MICROPY_NLR_SETJMP

nlr_buf_t *nlr_setjmp_top;

void nlr_setjmp_jump(void *val) {
    nlr_buf_t *buf = nlr_setjmp_top;
    nlr_setjmp_top = buf->prev; // <-- EXC_BAD_ACCESS
    buf->ret_val = val;
    longjmp(buf->jmpbuf, 1);
}

#endif
How do I go about debugging this? All of this setjmp business is very confusing to me.

π

User avatar
dhylands
Posts: 3821
Joined: Mon Jan 06, 2014 6:08 pm
Location: Peachland, BC, Canada
Contact:

Re: EXC_BAD_ACCESS in nlrsetjmp.c

Post by dhylands » Tue Sep 23, 2014 1:01 am

This looks like buf is set to NULL or an invalid pointer of some type.

Looking at the backtrace will give you a clue about what type of failure its trying to report. Without being able to see the backtrace, I probably can't help much.

Each time nlr_push is called it calls setjmp, which populates a jump buffer, and then nlr_push puts them on a linked list. nlr_setjmp_top should point to the most recent nlr_buf_t.
The very first call to nlr_push happens from within the do_str function. So you should be able to follow the list of buffers starting at nlr_setjmp_top and eventually winding up at the buffer do_str. These jump buffers should all be coming from the stack. If the buffers look corrupt, then you'll need to figure out why. nlr_setjmp_top should be NULL initially, and then if you set a breakpoint just after nlr_push and verify that after calling the first nlr_push that nlr_setjmp_top points to the buffer (the prev in this very first buffer isn't initialized, so you won't be able to follow beyond it, but you should never need to since nlr_push's should always have a matching nlr_pop).

Then single step through the code. There will probably be other places where nlr_push is called. After they're called, you should again be able to validate the linked list.

Did you compile with MICROPY_ENABLE_GC set? If so, then you're probably missing a call to gc_init. See: https://github.com/micropython/micropyt ... #L285-L288

p-i-
Posts: 20
Joined: Sun Sep 14, 2014 2:24 pm

Re: EXC_BAD_ACCESS in nlrsetjmp.c

Post by p-i- » Tue Sep 23, 2014 12:44 pm

Thankyou, gc_init() solved it!

pfalcon
Posts: 1155
Joined: Fri Feb 28, 2014 2:05 pm

Re: EXC_BAD_ACCESS in nlrsetjmp.c

Post by pfalcon » Sun Oct 12, 2014 11:10 am

p-i-, I see that you posted quite a lot of development-related topics to "General" forum. They all were moved to "Development" forum, and please post your future question there too. Thanks.
Awesome MicroPython list
Pycopy - A better MicroPython https://github.com/pfalcon/micropython
MicroPython standard library for all ports and forks - https://github.com/pfalcon/micropython-lib
More up to date docs - http://pycopy.readthedocs.io/

stijn
Posts: 735
Joined: Thu Apr 24, 2014 9:13 am

Re: EXC_BAD_ACCESS in nlrsetjmp.c

Post by stijn » Sun Oct 12, 2014 7:02 pm

I don't think p-i- is around anymore: there was a burst of posts to get Micropython embedded in another project by just including source files in that project which naturally leads to all kinds of problems. Then suddenly nothing anymore so I'd guess he/she gave up eventually.

pfalcon
Posts: 1155
Joined: Fri Feb 28, 2014 2:05 pm

Re: EXC_BAD_ACCESS in nlrsetjmp.c

Post by pfalcon » Sun Oct 12, 2014 8:39 pm

I guess so. Anyway, figuring I move ~dozen of topics to another subforum, I didn't want that to be silent, to avoid situation like a guy comes back in a month and says "hey, were all my topics just removed??".
Awesome MicroPython list
Pycopy - A better MicroPython https://github.com/pfalcon/micropython
MicroPython standard library for all ports and forks - https://github.com/pfalcon/micropython-lib
More up to date docs - http://pycopy.readthedocs.io/

Post Reply