【问题标题】:print sqlite3_exec error message cause segmentation fault in C打印 sqlite3_exec 错误消息导致 C 中的分段错误
【发布时间】:2017-07-03 08:24:27
【问题描述】:

我在 C 中使用 sqlite3 和 ubuntu 14.04。 在我的过程中,我每 20 分钟更新一次数据库。

这是我的功能:

int update_alive_state(uint64_t ieee,bool isAlive)
{
    char *error_report = NULL;
    char sql[100];
    int result = -1;
    UpdateAliveStateSql(sql,ieee,isAlive);
    if(result = sqlite3_exec(db_event, sql, 0, 0, &error_report))
    {
        printf( "\t> CMD: %s , Error: %s\n" , sql , error_report );
        sqlite3_free(error_report);
    }

    return result;
}

sqlite3_exec() 返回错误并打印错误消息时,我收到分段错误消息并且进程终止。

ERROR: signal 11 was trigerred:
  Fault address: 0xae703f1b
  Fault reason: address not mapped to object
Stack trace folows:
./main.bin(segmentation_fault_handler+0xd5)[0x419e9f]
/lib/x86_64-linux-gnu/libpthread.so.0(+0x10330)[0x7fa386f20330]
/lib/x86_64-linux-gnu/libc.so.6(_IO_vfprintf+0x1d03)[0x7fa386257943]
/lib/x86_64-linux-gnu/libc.so.6(_IO_printf+0x99)[0x7fa3862603d9]
./main.bin(update_alive_state+0x15d)[0x43ca78]
./main.bin(EventScanThread+0x2af)[0x442c21]
/lib/x86_64-linux-gnu/libpthread.so.0(+0x8184)[0x7fa386f18184]
/lib/x86_64-linux-gnu/libc.so.6(clone+0x6d)[0x7fa38630637d]
Executing original handler...

如果我注释掉printfsqlite3_free,分段错误消息将消失。 为什么我不能打印错误信息?

请帮帮我。


编辑: 我像这样更改了我的代码

if(result = sqlite3_exec(db, sql, 0, 0, &error_report))
{
    printf( "[ERR] : \t> CMD: %s , Error: %d\n" , sql , result );
    if ( error_report )
    {
        printf( "[ERR] : Error msg: %s\n", error_report );
        sqlite3_free(error_report);
    }
}

但我仍然收到分段错误消息。

ERROR: signal 11 was trigerred:
  Fault address: 0x7f3dc490cf1b
  Fault reason: address not mapped to object
Stack trace folows (partial):
./main.bin(segmentation_fault_handler+0xd5)[0x419e9f]
/lib/x86_64-linux-gnu/libpthread.so.0(+0x10330)[0x7fab749ac330]
/lib/x86_64-linux-gnu/libc.so.6(_IO_vfprintf+0x1d03)[0x7fab73ce3943]
/lib/x86_64-linux-gnu/libc.so.6(_IO_printf+0x99)[0x7fab73cec3d9]
./main.bin(update_last_receive_time+0x166)[0x43d60e]
./main.bin(attr_process_attribute_report_ind+0x97)[0x4222dc]
./main.bin(si_gateway_incoming_data_handler+0xa3)[0x41b6b1]
./main.bin(tcp_socket_event_handler+0x558)[0x41c316]
./main.bin(polling_process_activity+0xde)[0x41a4e1]
./main.bin(main+0x150)[0x41a0f4]
Executing original handler...

错误地址指向第一个printf函数

printf( "[ERR] : \t> CMD: %s , Error: %d\n" , sql , result );

为什么?请帮我。谢谢。

【问题讨论】:

  • 如果您在调试器中发现崩溃,那么值是多少或error_report?它可能是一个空指针吗?
  • sqlite3_exec 需要一个指向 char 的双指针作为最后一个参数,但您正在打印它 (error_report),就好像它是一个普通字符串一样。
  • @FedericoklezCulloca sqlite3_exec 函数期望一个指向指针(指向char)的指针作为模拟传递引用的一种方式,因此它可以将原始指针设置为指向一个字符串.并且 OP 将正确的东西传递给sqlite3_exec(指向char 的指针的指针),因为它应该是一个字符串,所以它被打印为一个也是正确的字符串。正如我在之前的评论中提到的那样,问题可能是没有错误消息并且sqlite3_execerror_report 留下为空指针。
  • 感谢@Some程序员老兄,我想每个 sqlite3_exec() 错误代码都有错误消息。我会尝试检查 (error_report) 是否为 NULL。

标签: c sqlite


【解决方案1】:

documentation 声明:

如果 sqlite3_exec() 的第 5 个参数不为 NULL 并且没有发生错误,则 sqlite3_exec() 在返回之前将其第 5 个参数中的指针设置为 NULL。

因此可能根本没有错误消息,您应该这样做:

if (result = sqlite3_exec(db_event, sql, NULL, NULL, &error_report))
{
   if (error_report)
   {
      printf( "\t> CMD: %s , Error: %s\n" , sql , error_report );
      sqlite3_free(error_report);
   }
}

检查它是否设置为NULL


我像这样更改了我的代码 [...]
但我仍然收到分段错误消息。 [...]
错误地址指向第一个printf函数:

printf( "[ERR] : \t> CMD: %s , Error: %d\n" , sql , result );

如果您使用%s 打印字符数组,printf 需要以空结尾的'\0' C-string。由于您没有提供 UpdateAliveStateSql 函数,因此我看不到 sql 字符串是否以空值结尾。为了确保通过在缓冲区末尾写入'\0',您可以这样做:

sql[sizeof(sql) - 1] = '\0';

调用UpdateAliveStateSql函数后。

【讨论】:

  • 谢谢@Andre Kampling,那我试试。
  • @FrazierChang:当我看到您编辑了您的问题时,我扩展了我的答案。请告知状态。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多