2016-01-24 90 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()給出的堆的原始內存地址。

相關問題