c linux - memset 在发布版本中引发分段错误,printf 不知何故可以 'fix' 吗?
c linux - memset raise Segmentation Fault in Release build, printf somehow can 'fix' it?
我在 CentOS 7 64 位版本上遇到分段错误(调试版本没有问题)
我尝试添加 printf 来定位段错误发生的确切位置,对于以下代码,段错误在以下位置引发:memset(len_p, 0, sizeof(*len_p));
此外,如果我在 memeset 之前添加 printf 以打印某些内容,则不会出现段错误,就好像 printf 在这里施展魔法一样。
请帮助我理解这里的问题。
core dump 已上传
非常感谢!
代码片段(mysql 准备好的查询语句):
(这个函数被调用了几次,它并不总是引发段错误)
int mysql_odb_read(void **data_p, size_t *len_p, git_otype *type_p, git_odb_backend *_backend, const git_oid *oid)
{
MYSQL_BIND bind_buffers[2];
MYSQL_BIND result_buffers[3];
memset(bind_buffers, 0, sizeof(bind_buffers));
// bind the repo passed to the statement
bind_buffers[0].buffer = &(backend->mysql->repo);
bind_buffers[0].buffer_length = sizeof(backend->mysql->repo);
bind_buffers[0].length = &bind_buffers[0].buffer_length;
bind_buffers[0].buffer_type = MYSQL_TYPE_LONGLONG;
// bind the oid passed to the statement
bind_buffers[1].buffer = (void*)oid->id;
bind_buffers[1].buffer_length = 20;
bind_buffers[1].length = &bind_buffers[1].buffer_length;
bind_buffers[1].buffer_type = MYSQL_TYPE_BLOB;
if (mysql_stmt_bind_param(backend->mysql->odb_read, bind_buffers) != 0)
return GIT_ERROR;
// execute the statement
if (mysql_stmt_execute(backend->mysql->odb_read) != 0)
return GIT_ERROR;
if (mysql_stmt_store_result(backend->mysql->odb_read) != 0)
return GIT_ERROR;
if (mysql_stmt_num_rows(backend->mysql->odb_read) == 1) {
memset(result_buffers, 0, sizeof(result_buffers));
result_buffers[0].buffer_type = MYSQL_TYPE_TINY;
result_buffers[0].buffer = type_p;
result_buffers[0].buffer_length = sizeof(*type_p);
result_buffers[0].is_null = 0;
result_buffers[0].length = &result_buffers[0].buffer_length;
memset(type_p, 0, sizeof(*type_p));
result_buffers[1].buffer_type = MYSQL_TYPE_LONG;
result_buffers[1].buffer = len_p;
result_buffers[1].buffer_length = sizeof(*len_p);
result_buffers[1].is_null = 0;
result_buffers[1].length = &result_buffers[1].buffer_length;
printf("len_p:%lu\n",*len_p);//if i remove this printf call, there will be segfault
memset(len_p, 0, sizeof(*len_p));
result_buffers[2].buffer_type = MYSQL_TYPE_LONG_BLOB;
result_buffers[2].buffer = *data_p;
result_buffers[2].is_null = 0;
result_buffers[2].buffer_length = data_len;
result_buffers[2].length = &data_len;
//memset(&data_len, 0, sizeof(data_len));
if (mysql_stmt_bind_result(backend->mysql->odb_read, result_buffers) != 0)
return GIT_ERROR;
error = mysql_stmt_fetch(backend->mysql->odb_read);
if (data_len > 0) {
*data_p = malloc(data_len);
if(*data_p){
result_buffers[2].buffer_type = MYSQL_TYPE_LONG_BLOB;
result_buffers[2].buffer = *data_p;
result_buffers[2].is_null = 0;
result_buffers[2].buffer_length = data_len;
result_buffers[2].length = &data_len;
if (mysql_stmt_fetch_column(backend->mysql->odb_read, &result_buffers[2], 2, 0) != 0)
return GIT_ERROR;
}
else{
printf("odb_read, malloc returned NULL\n");
return GITERR_NOMEMORY;
}
}
error = GIT_OK;
} else
error = GIT_ENOTFOUND;
// free result
if (mysql_stmt_free_result(backend->mysql->odb_read) != 0)
return GIT_ERROR;
mysql_free_result(meta_result);
// reset the statement for further use
if (mysql_stmt_reset(backend->mysql->odb_read) != 0)
return GIT_ERROR;
return error;
}
如果没有转储或其他信息,很难说出确切的问题,但可能的解释是 len_p
是一个悬挂指针。
这会触发段错误,但是,通过调用 printf
,您可能正在用 printf
数据填充 len_p
指向的堆栈区域,因此重新映射指针一个新值,避免分段错误。
我在 CentOS 7 64 位版本上遇到分段错误(调试版本没有问题)
我尝试添加 printf 来定位段错误发生的确切位置,对于以下代码,段错误在以下位置引发:memset(len_p, 0, sizeof(*len_p));
此外,如果我在 memeset 之前添加 printf 以打印某些内容,则不会出现段错误,就好像 printf 在这里施展魔法一样。
请帮助我理解这里的问题。
core dump 已上传
非常感谢!
代码片段(mysql 准备好的查询语句):
(这个函数被调用了几次,它并不总是引发段错误)
int mysql_odb_read(void **data_p, size_t *len_p, git_otype *type_p, git_odb_backend *_backend, const git_oid *oid)
{
MYSQL_BIND bind_buffers[2];
MYSQL_BIND result_buffers[3];
memset(bind_buffers, 0, sizeof(bind_buffers));
// bind the repo passed to the statement
bind_buffers[0].buffer = &(backend->mysql->repo);
bind_buffers[0].buffer_length = sizeof(backend->mysql->repo);
bind_buffers[0].length = &bind_buffers[0].buffer_length;
bind_buffers[0].buffer_type = MYSQL_TYPE_LONGLONG;
// bind the oid passed to the statement
bind_buffers[1].buffer = (void*)oid->id;
bind_buffers[1].buffer_length = 20;
bind_buffers[1].length = &bind_buffers[1].buffer_length;
bind_buffers[1].buffer_type = MYSQL_TYPE_BLOB;
if (mysql_stmt_bind_param(backend->mysql->odb_read, bind_buffers) != 0)
return GIT_ERROR;
// execute the statement
if (mysql_stmt_execute(backend->mysql->odb_read) != 0)
return GIT_ERROR;
if (mysql_stmt_store_result(backend->mysql->odb_read) != 0)
return GIT_ERROR;
if (mysql_stmt_num_rows(backend->mysql->odb_read) == 1) {
memset(result_buffers, 0, sizeof(result_buffers));
result_buffers[0].buffer_type = MYSQL_TYPE_TINY;
result_buffers[0].buffer = type_p;
result_buffers[0].buffer_length = sizeof(*type_p);
result_buffers[0].is_null = 0;
result_buffers[0].length = &result_buffers[0].buffer_length;
memset(type_p, 0, sizeof(*type_p));
result_buffers[1].buffer_type = MYSQL_TYPE_LONG;
result_buffers[1].buffer = len_p;
result_buffers[1].buffer_length = sizeof(*len_p);
result_buffers[1].is_null = 0;
result_buffers[1].length = &result_buffers[1].buffer_length;
printf("len_p:%lu\n",*len_p);//if i remove this printf call, there will be segfault
memset(len_p, 0, sizeof(*len_p));
result_buffers[2].buffer_type = MYSQL_TYPE_LONG_BLOB;
result_buffers[2].buffer = *data_p;
result_buffers[2].is_null = 0;
result_buffers[2].buffer_length = data_len;
result_buffers[2].length = &data_len;
//memset(&data_len, 0, sizeof(data_len));
if (mysql_stmt_bind_result(backend->mysql->odb_read, result_buffers) != 0)
return GIT_ERROR;
error = mysql_stmt_fetch(backend->mysql->odb_read);
if (data_len > 0) {
*data_p = malloc(data_len);
if(*data_p){
result_buffers[2].buffer_type = MYSQL_TYPE_LONG_BLOB;
result_buffers[2].buffer = *data_p;
result_buffers[2].is_null = 0;
result_buffers[2].buffer_length = data_len;
result_buffers[2].length = &data_len;
if (mysql_stmt_fetch_column(backend->mysql->odb_read, &result_buffers[2], 2, 0) != 0)
return GIT_ERROR;
}
else{
printf("odb_read, malloc returned NULL\n");
return GITERR_NOMEMORY;
}
}
error = GIT_OK;
} else
error = GIT_ENOTFOUND;
// free result
if (mysql_stmt_free_result(backend->mysql->odb_read) != 0)
return GIT_ERROR;
mysql_free_result(meta_result);
// reset the statement for further use
if (mysql_stmt_reset(backend->mysql->odb_read) != 0)
return GIT_ERROR;
return error;
}
如果没有转储或其他信息,很难说出确切的问题,但可能的解释是 len_p
是一个悬挂指针。
这会触发段错误,但是,通过调用 printf
,您可能正在用 printf
数据填充 len_p
指向的堆栈区域,因此重新映射指针一个新值,避免分段错误。