我正在使用MySQL C API并尝试执行预准备语句以删除行。
-(void) deleteOne:(int) num
{
[self initAndConnectSql];
char copy[30] = "call delete";
strncat(copy, _name, 15);
strncat(copy, "(?)", 4);
MYSQL_STMT * prepared = mysql_stmt_init(&_mysql);
mysql_stmt_prepare(prepared, copy, strlen(copy));
MYSQL_BIND bind[1];
bind[0].buffer_type = MYSQL_TYPE_LONG;
bind[0].buffer = #
bind[0].is_null=0;
bind[0].length= 0;
if (mysql_stmt_bind_param(prepared, bind))
{
printf("error in binding params");
exit(1);
}
if (mysql_stmt_execute(prepared))
{
printf("Error executing prepared statement");
exit(1);
}
mysql_stmt_close(prepared);
mysql_close(&_mysql);
}
此代码工作正常。但是之前当我没有将准备好的变量设置为指针时,我得到了一个被释放的指针,没有在malloc_error_break中设置断点来调试错误。该行是MYSQL_STMT prepared = *mysql_stmt_init(&_mysql);
。
我的问题是为什么设置准备作为指针,而不是传入和准备好需要的地方,工作?不应该指针和&是等价的,因为指针存储了它指向的地址和&返回地址,所以对于一个函数,它们是一样的吗?
答案 0 :(得分:1)
来自manual for mysql_stmt_close
:
关闭准备好的声明。 mysql_stmt_close()也解除了分配 stmt。指向的语句句柄。
如果你这样做:
MYSQL_STMT prepared = *mysql_stmt_init(&_mysql);
mysql_stmt_close(&prepared);
将指向堆栈变量的指针传递到mysql_stmt_close
函数,然后尝试free
它会导致您看到的错误。相反,您必须传递mysql_stmt_init
返回的原始指针,如第一个代码段所示。 mysql_stmt_init
返回动态内存(通过malloc
或类似函数获取),然后需要mysql_stmt_close
释放。
答案 1 :(得分:0)
来自MySQL API:
belongs_to :item
23.8.11.15 mysql_stmt_init()
----------------------------
MYSQL_STMT *mysql_stmt_init(MYSQL *mysql)
Description
Create a MYSQL_STMT handle. The handle should be freed with mysql_stmt_close(MYSQL_STMT *).
函数将指针返回给mysql_stmt_init()
。该部分说它应该被释放"意味着它是从堆动态分配的。返回的值是此堆内存的内存地址(指针)。要正确释放它,必须将相同的内存地址(指针值)赋予MYSQL_STMT
。
当您使用原始mysql_stmt_close()
版本时,您将MYSQL_STMT prepared = *mysql_stmt_init(&_mysql);
的值复制到位于堆栈中的本地变量MYSQL_STMT
中。当您将此地址提供给prepared
时,您没有从mysql_stmt_close(&prepared)
给出的堆中提供原始内存地址。