c linux - memset在Release版本中引发Segmentation Fault,printf以某种方式可以“修复”它吗?

时间:2015-06-23 15:10:17

标签: mysql c linux libmysql

我在CentOS 7 64位,发布版本上遇到分段错误(在调试版本中没有问题)

我尝试添加printf来找到segfault发生的确切位置,对于下面的代码,segfault引发: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;
}

1 个答案:

答案 0 :(得分:1)

如果没有转储或其他信息,很难说出确切的问题,但可能的解释可能是len_p是一个悬空指针。

这会触发段错误,但是,通过调用printf,您可能正在填充len_p所指向的堆栈区域,并使用printf数据,因此重新映射指针值,避免分割错误。