2013-05-06 170 views
0

這是我的代碼:堆棧溢出錯誤

#include <mysql.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

char *server = "nope"; 
    char *user = "nope"; 
    char *password = "nope"; 
    char *database = "nope"; 
    unsigned int port = 0; 

int cprint(char *text){//Imprime como encabezado el numero de productos sin stock sumado al argumento 
    MYSQL *conn; 
    MYSQL_RES *res; 
    my_ulonglong num; 

    conn = mysql_init(NULL); 

    /* Connect to database */ 
    if (!mysql_real_connect(conn, server, 
    user, password, database, port, NULL, 0)) { 
     fprintf(stderr, "%s\n", mysql_error(conn)); 
     exit(1); 
    } 

    /* send SQL query */ 
    if (mysql_query(conn, "SELECT id FROM productos WHERE stock <= 0")) { 
     fprintf(stderr, "%s\n", mysql_error(conn)); 
     exit(1); 
    } 

    res = mysql_store_result(conn); 
    num = mysql_num_rows(res); 

    printf("\n===============================\n\n"); 
    if(num > 0){ 
     printf("Productos sin stock: %llu\n",num); 
    } 
    else{ 
     printf("No hay productos sin stock\n"); 
    } 
    printf("\n===============================\n\n%s",text); 

    /*close connection */ 
    mysql_free_result(res); 
    mysql_close(conn); 

return 0; 
} 

char *remove_newline(char *s) 
{ 
    int len = strlen(s); 

    if (len > 0 && s[len-1] == '\n') // if there's a newline 
     s[len-1] = '\0';   // truncate the string 

    return s; 
} 

int newproduct(){ 
    char *name = malloc(127*sizeof(char));//nombre del producto 
    char *desc = malloc(127*sizeof(char));//descripcion del producto 
    double price;//precio del producto 
    cprint("Agregar nuevo producto\n\n"); 
    printf("Nombre del producto: "); 
    fgets(name, 127, stdin); 
    name = remove_newline(name); 
    printf("Descripcion: "); 
    fgets(desc, 127, stdin); 
    name = remove_newline(desc); 
    printf("Precio: "); 
    scanf("%e", &price); 

    MYSQL *conn; 
    conn = mysql_init(NULL); 
    printf("Mysql initiated\n"); 
    if (!mysql_real_connect(conn, server, 
    user, password, database, port, NULL, 0)) { 
     fprintf(stderr, "%s\n", mysql_error(conn)); 
     exit(1); 
    } 
    printf("connection established\n"); 
    char rname[256];//string donde guardar el nombre con caracteres de escape 
    char rdesc[256]; 
    printf("Vars declared\n"); 
    mysql_real_escape_string(conn,rname,name,256);//se agregan los caracteres de escape 
    printf("name escaped\n"); 
    mysql_real_escape_string(conn,rdesc,desc,256); 
    printf("desc escaped\n"); 
    /* 
    char *query;//donde guardar el query 

    snprintf(query,1000,"INSERT INTO productos (nombre,descripcion,stock,precio) VALUES(%s,%s, 0, %e)",rname,rdesc,price);//query a enviar 

    if (mysql_query(conn, query)) {//enviar el query 
     fprintf(stderr, "%s\n", mysql_error(conn)); 
     exit(1); 
    }*/ 

    mysql_close(conn); 
    printf("Mysql closed\n"); 
return 0; 
} 


int main(){ 
    printf("Sales Assistant Alpha v0.0\n");//Nombre y version del programa 
    unsigned int choice;//numero de eleccion del menu 
    char *err = NULL;//Error 
    while(1){//loop infinito 
     cprint("Menu Principal\n\n");//imprime el encabezado 
     printf("1-Agregar nuevo producto\n"); 
     printf("2-Editar producto existente\n"); 
     printf("3-Productos sin stock\n"); 
     printf("4-Agregar pedido\n"); 
     printf("5-Salir de la aplicacion\n\n"); 

     if(err != NULL){//evalua si hubo un error y lo imprime 
      printf("%s\n",err); 
      err = NULL; 
     } 



     printf("Numero de eleccion: "); 
     scanf("%i",&choice);//pide eleccion 
     if (scanf("%*[^\n]") != EOF){//read and discard all non-newlines 
     scanf("%*c"); //then read and discard the newline 
     } 
     switch(choice){//evalua la eleccion y ejecuta la funcion correspondiente 
      case 1: 
       newproduct(); 
       printf("returned\n"); 
       break; 
      case 2: 
       break; 
      case 3: 
       break; 
      case 4: 
       break; 
      case 5: 
       exit(0);//termina el programa 
       break; 
      default: 
       err = "Eleccion no valida";//error 
       break; 
     } 
    } 
return 0; 
} 

和控制檯執行:

Sales Assistant Alpha v0.0 

=============================== 

Productos sin stock: 3 

=============================== 

Menu Principal 

1-Agregar nuevo producto 
2-Editar producto existente 
3-Productos sin stock 
4-Agregar pedido 
5-Salir de la aplicacion 

Numero de eleccion: 1 

=============================== 

Productos sin stock: 3 

=============================== 

Agregar nuevo producto 

Nombre del producto: a 
Descripcion: a 
Precio: 1 
Mysql initiated 
connection established 
Vars declared 
name escaped 
desc escaped 
Mysql closed 
*** stack smashing detected ***: ./sales_assistant terminated 
Aborted (core dumped) 


------------------ 
(program exited with code: 134) 
Press return to continue 

我有這個堆棧溢出來說是未知的我的東西。除此之外,我想知道我可以安全地分配多少內存而不會出現總線錯誤。

重要提示:當我禁用mysql_real_escape_string函數代碼正常工作,所以問題在那裏,但我不知道問題是什麼。

謝謝,亞光。

編輯 新增的完整代碼,並翻譯成英文。也改變了這個問題,因爲我得到了一個新的錯誤。增加了調試代碼。

+1

在調用newproduct()的過程中會發生什麼? fgets「不工作」的一個常見原因是之前調用scanf在輸入流中留下'/ n'。 – 2013-05-06 22:25:34

+1

在你調用'newproduct'之前會發生什麼?看起來'stdin'是borked。我們可以看到'remove_newline'的代碼嗎? – 2013-05-06 22:27:06

+0

我擡頭看看'/ n'的東西,我解決了!非常感謝你奈傑爾! – Arheisel 2013-05-06 23:44:09

回答

0

您的malloc()是錯誤的(字符*)

應該是:

char *name = malloc(127*sizeof(char));//nombre del producto 
char *desc = malloc(127*sizeof(char)); 
+0

謝謝,我不知道 – Arheisel 2013-05-06 22:20:27

+2

sizeof(char)總是1,所以這個「更正」不會改變任何東西。 – 2013-05-06 22:22:02

2

當你問一些與scanf("%i", &choice);(其結果應檢查!),你留下換行符。當您在newproduct()中讀取一行fgets()時,它會讀取留下的換行符。

最終,如果您正在執行基於行的輸入,請使用fgets()readline()(來自POSIX 2008)讀取該行,並使用sscanf()解析該行。

+0

感謝您的回答。但我改變了問題,因爲我得到了另一個錯誤,我不想爲相同的代碼提出一個全新的問題。 – Arheisel 2013-05-06 23:49:54

+1

它讓生活變得困難,不是嗎?你已經在你的程序中得到了'remove_newline()'的代碼兩次!代碼中的'價格'跟蹤'Precio'?你的調試器在哪裏說崩潰發生了?你主要使用'Price'輸入後的MySQL庫代碼,所以你有可能會錯誤地調用某些東西。在各種函數調用之間添加調試打印,以便您知道失敗的內容(如果無法在調試器中執行)。做一個最簡單的測試用例(參見[Simple,Self-Contained,Complete Example](http://sscce.org/),瞭解如何以及爲什麼)。 – 2013-05-06 23:58:27

+0

代碼是西班牙文,我翻譯它在這裏,但我做得很糟糕,因爲我看到。對不起。 remove_newline重複也是一個複製粘貼錯誤,它在原始代碼中只有一次。 – Arheisel 2013-05-07 00:04:20

0

問題的確是mysql_real_escape_string()。事情是,長度參數必須是長度而不是長度,就像我在做的那樣。我非常高興,我工作的事情,我變得非常沮喪。