C API를 사용하여 mysql 5.5를 쿼리하려고한다. 이Segfault mysql_stmt_close
을 칠 때#include "../include/dbutil.h"
int main() {
MYSQL conn = get_connection("localhost", "user", "pass", "test");
MYSQL_STMT stmt = prepare_stmt(&conn, "SELECT hostname from hosts where id = ?");
MYSQL_BIND param[1], result[1];
memset(param, 0, sizeof(param));
memset(result, 0, sizeof(result));
int in = 1;
unsigned long length = 200;
my_bool isNull[2];
isNull[0] = 0;
char out[200];
bind_param(¶m[0], MYSQL_TYPE_LONG, (char *) &in, &isNull[0], (unsigned long *)0);
bind_string_result(&result[0], 200, (char *) &out, &isNull[1], &length);
mysql_stmt_bind_param(&stmt, param);
mysql_stmt_execute(&stmt);
mysql_stmt_bind_result(&stmt, result);
mysql_stmt_store_result(&stmt);
mysql_stmt_fetch(&stmt);
printf("Restult %s\n", out);
mysql_stmt_close(&stmt);
mysql_close(&conn);
return 0;
}
문이 실행하고 예상 된 결과를 반환하지만 코드 세그먼테이션 폴트 (segfault) : 여기
#include "../include/dbutil.h"
#include "../include/logging.h"
#include "../include/common.h"
MYSQL get_connection(char *host, char *user, char *passwd, char *db) {
MYSQL conn;
mysql_init(&conn);
if (!mysql_real_connect(&conn, host, user, passwd, db, 0, NULL, 0)) {
log_to_console("Cannot connect to MySQL server: %s", mysql_error(&conn));
exit(1);
}
return conn;
}
MYSQL_STMT prepare_stmt(MYSQL *conn, char *sql) {
MYSQL_STMT *stmtP = mysql_stmt_init(conn);
if (!stmtP) {
log_to_console("Cannot create statement, out of memory.");
exit(1);
}
MYSQL_STMT stmt = *stmtP;
if (mysql_stmt_prepare(&stmt, sql, strlen(sql))) {
log_to_console("Preparing statement failed: %s", mysql_error(conn));
exit(1);
}
return stmt;
}
void bind_param(MYSQL_BIND *param, enum enum_field_types fieldType, char* buffer, my_bool *isNull, unsigned long *length) {
param->buffer_type = fieldType;
param->buffer = buffer;
param->is_null = isNull;
param->length = length;
}
void bind_string_param(MYSQL_BIND *param, int stringSize, char* buffer, my_bool *isNull, unsigned long *length) {
bind_param(param, MYSQL_TYPE_STRING, buffer, isNull, length);
param->buffer_length = stringSize;
}
void bind_result(MYSQL_BIND *result, enum enum_field_types fieldType, char* buffer, my_bool *isNull, unsigned long *length) {
bind_param(result, fieldType, buffer, isNull, length);
}
void bind_string_result(MYSQL_BIND *result, int stringSize, char* buffer, my_bool *isNull, unsigned long *length) {
bind_string_param(result, stringSize, buffer, isNull, length);
}
실제로 쿼리를 실행하는 코드입니다 :
dbutil.c은 상용구 코드가 포함되어 있습니다
mysql_stmt_close(&stmt);
코어 덤프 주위를 뚫고 segfault가 libc free() 문에 의해 발생한다는 것을 발견했습니다.이 문은 f libmysql.c의 ree_root()를
my_bool STDCALL mysql_stmt_close(MYSQL_STMT *stmt)
{
MYSQL *mysql= stmt->mysql;
int rc= 0;
DBUG_ENTER("mysql_stmt_close");
free_root(&stmt->result.alloc, MYF(0));
free_root(&stmt->mem_root, MYF(0));
free_root(&stmt->extension->fields_mem_root, MYF(0));
...
으로 지정하십시오. 코어 덤프는 * stmt.extension이 명령문 닫기가 발생한다고 말합니다. 왜 그런 아이디어가 있니?
실제로 문제는 mysql_init (& conn)입니다. 어떤 이유로 conn이 초기화되지 않습니다. conn을 초기화하고 get_connection에 전달하면 모든 것이 예상대로 작동합니다. – cbaby