2016-01-24 144 views
1

我正在使用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

'mysql_stmt_init'返回的类型是什么? “MYSQL_STMT”和“MYSQL_STMT *”类型有所不同吗?回答这两个问题是否回答你的问题? – dho

+1

在需要求助于运行调试器之前,您应该已经获得了类型不匹配的编译器警告。您是否由于某种原因禁用了警告? –

+0

我没有。编译器没有发出任何警告。 init函数返回一个指向MYSQL_stmt结构的指针。事实上,编译器实际上建议我在函数前面插入*而不是准备好,并且在执行到达stmt_close之前不会抛出任何错误。 –

回答

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释放。

+0

好吧,我想我明白了。所以基本上,因为我没有声明准备作为指针变量,它实际上是一个局部变量在这个函数内,因此在堆栈上?这个堆栈变量的值是由mysql_stmt_init创建的动态内存的地址吗?因为我已经准备好了init的返回值,这是一个指针。 –

+0

“这个栈变量的值是由mysql_stmt_init创建的动态内存的地址吗?”。不完全的。堆栈变量的值是由'mysql_stmt_init'的返回值指向的值的副本。在执行该行后,由'mysql_stmt_init'返回的原始指针/内存会丢失(即导致内存泄漏的悬挂指针)。 – kaylum

+0

我明白了。谢谢回答。这是我第一次进入C领域,因此我仍然试图围绕堆栈/堆和指针进行打包。 –

0

MySQL API

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)时,你没有给你从mysql_stmt_init()给出的堆的原始内存地址。

相关问题