【问题标题】:Calling my function, causes the program to crash - C | 3DS Homebrew调用我的函数,导致程序崩溃 - C | 3DS 自制
【发布时间】:2015-08-26 18:58:48
【问题描述】:

我一直在为 Nintendo 3DS 编写一个自制软件,它是用 C 语言编写的。它只是解析一个 JSON 文件并将其打印到屏幕上。问题是解析并在屏幕上打印后,它就崩溃了。

代码:

char JSON_FILE[] = "jsbr-ford-mustang.json";
static int jsoneq(const char *json, jsmntok_t *tok, const char *s) {
    if (tok->type == JSMN_STRING && (int) strlen(s) == tok->end - tok->start &&
        strncmp(json + tok->start, s, tok->end - tok->start) == 0) {
        return 0;
    }
    return -1;
}

const char * parse_json(char* value) {
    u8* file_buffer; FILE *file = fopen(JSON_FILE,"rb"); if (file == NULL) printf("Error.\n");
    fseek(file,0,SEEK_END); off_t size = ftell(file); fseek(file,0,SEEK_SET); file_buffer=malloc(size);
    if(!file_buffer) printf("Error.\n");
    off_t bytesRead = fread(file_buffer,1,size,file); fclose(file);
    if(size!=bytesRead) printf("Error.\n");
    int i; int r;
    jsmn_parser p; jsmntok_t t[128]; jsmn_init(&p);
    r = jsmn_parse(&p, file_buffer, size, t, sizeof(t)/sizeof(t[0]));

    if (r < 0) {
        printf("Failed to parse JSON: %d\n", r);
        return 1;
    }
    if (r < 1 || t[0].type != JSMN_OBJECT) {
        printf("Object expected\n");
        return 1;
    }
    printf("Debug START\n");
    for (i = 1; i < r; i++) {
        if (jsoneq(file_buffer, &t[i], value) == 0) {
            printf("Debug 1\n");
            break;
        }
        printf("Debug 2\n");
    }
    printf("Debug 3\n");
    return printf("%.*s\n", t[i+1].end-t[i+1].start, file_buffer + t[i+1].start);
}

int main() {
    gfxInitDefault();
    consoleInit(GFX_TOP,NULL);
    printf("P1\n");
    printf("Description: %s",parse_json("description"));
    printf("P2\n");
    printf("Sync spacing: %s",parse_json("synchronization_spacing_us"));
    while (aptMainLoop()) {
        hidScanInput(); u32 kDown = hidKeysDown();
        if(kDown & KEY_START) {
            consoleClear();
            break;
        }
        gfxFlushBuffers();
        gfxSwapBuffers();
    }
    gfxExit();
    return 0;
}

调试输出:

P1
Debug START
Debug 2
Debug 2
Debug 1
Debug 3
Ford Mustang, 40MHz, No. 23019

这里是发生了什么的视频:https://www.youtube.com/watch?v=zpt_BEMyIOc

这是我拥有的 GitHub 存储库:https://github.com/lavanoid/3DS_JSON_Parser

【问题讨论】:

  • 除了添加诊断 printfs 之外,您是否尝试过调试它?
  • 是的,我是 C 新手,但我尝试了各种小调整,但我没有运气:( 我不确定调试它的最佳方法是什么。跨度>
  • 比如printf("Description: %s"...)的效果为什么没有出现? (这应该几乎可以准确地告诉您崩溃的位置。)
  • 哦,我明白你的意思了。在成功返回printf("Description: %s"...) 的值后,它在到达“P2”时崩溃。
  • 所以我真的不知道是什么导致它崩溃:/

标签: c crash homebrew


【解决方案1】:

来自cplusplus.com关于printf()的返回值:

成功时,返回写入的字符总数。

如果发生写入错误,则设置错误指示符(ferror)并返回负数。

如果写入宽字符时出现多字节字符编码错误,则将errno设置为EILSEQ并返回一个负数。

你不能这样做:return printf("%.*s\n", t[i+1].end-t[i+1].start, file_buffer + t[i+1].start);

因为您的函数需要返回 const char *,而不是从 printf() 返回的 int

您应该使用 sprintf() 将您想要的字符串打印到缓冲区中(例如 tempString)

static char *tempString;
...
if(tempstring != NULL) {
    free(tempString);
    tempString = NULL;
}
tempString = (char *)malloc(t[i+1].end-t[i+1].start+1);
if(tempString != NULL) {
    sprintf(tempString,"%s", file_buffer + t[i+1].start);
    return (const char *)tempString;
} else {
    return "malloc error!";
}

【讨论】:

  • 当然,tempString 必须是指向 malloc 内存的指针,否则调用者将引用堆栈上的数组内容,该堆栈在子函数退出后不再有效。
  • 感谢您的代码示例 :) 我拿走了您的代码并添加了它,但它仍然使 3DS 崩溃回到主屏幕。真可惜。那好吧。我一定做错了什么。感谢您的回复。
  • 如果您对答案感到满意,请随时接受它
  • 我只需要解决最后一个错误。出于某种原因,它会打印出文件的其余部分。最新代码:github.com/lavanoid/3DS_JSON_Parser/blob/master/source/main.c
猜你喜欢
  • 1970-01-01
  • 2019-10-27
  • 1970-01-01
  • 2012-03-05
  • 2013-07-04
  • 1970-01-01
  • 2012-01-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多