【问题标题】:stack smashing error堆栈粉碎错误
【发布时间】:2013-05-06 22:05:34
【问题描述】:

这是我的代码:

#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 函数时,代码正常工作,所以问题就在那里,但我不知道问题是什么。

谢谢,马特。

已编辑 添加了完整的代码并翻译成英文。也改变了问题,因为我得到了一个新的错误。添加调试代码。

【问题讨论】:

  • 在调用 newproduct() 之前会发生什么? fgets“不工作”的一个常见原因是之前对 scanf 的调用在输入流中留下了 '/n'。
  • 致电newproduct 之前会发生什么?看起来stdin 很无聊。我们能看到remove_newline的代码吗?
  • 我查了 '/n' 的问题,我解决了!非常感谢 Nigel!

标签: mysql c stdin fgets stdio


【解决方案1】:

当你用scanf("%i", &amp;choice); 询问一个数字时(应该检查其结果!),你留下换行符。当您在newproduct() 中读取带有fgets() 的行时,它会读取留下的换行符。

最终,如果您正在进行基于行的输入,请使用 fgets()readline()(来自 POSIX 2008)读取该行并使用 sscanf() 解析该行。

【讨论】:

  • 感谢您的回答。但我改变了问题,因为我遇到了另一个错误,我不想为相同的代码提出一个全新的问题。
  • 这让生活变得困难,不是吗...您的程序中有两次remove_newline() 的代码! Precio 在代码中的跟踪 Price 中吗?您的调试器在哪里说崩溃发生了?您主要是在输入Price 之后使用 MySQL 库代码,因此您可能会误称某些东西。在各种函数调用之间添加调试打印,以便您知道失败的原因(如果您无法在调试器中执行此操作)。制作一个最小的测试用例(请参阅Simple, Self-Contained, Complete Example 以获取有关如何和为什么的指导)。
  • 代码是西班牙语的,我在这里翻译了它,但我做的很糟糕,因为我看到了。对此感到抱歉。 remove_newline 重复也是复制粘贴错误,在原始代码中只有一次。
【解决方案2】:

你的 malloc() 对于 (char*) 是错误的

应该是:

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

【讨论】:

  • sizeof(char) 始终为 1,因此此“更正”不会改变任何内容。
【解决方案3】:

问题确实是mysql_real_escape_string()。问题是长度参数必须是 *from lenght 而不是 *to lenght 就像我正在做的那样。我很高兴我解决了这个问题,我真的很沮丧。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-06-08
    • 1970-01-01
    • 1970-01-01
    • 2015-01-12
    • 1970-01-01
    • 2011-11-18
    • 1970-01-01
    相关资源
    最近更新 更多