Segfault提交查询

时间:2014-12-31 14:40:55

标签: mysql c segmentation-fault

我正在测试MySQL C API的包装器库,我试图插入一行。

我已在GDB中对其进行了测试,并且我的代码中的错误信息如下所示:

Breakpoint 1, cq_query (con=0x7fffffffe1c0, 
    query=0x6014a0 "INSERT INTO TaskType(state,parentID,displayName) VALUES(1,19,'boop')") at cqstatic.c:32
32      return mysql_query(con->con, query);

此查询字符串格式正确(我可以将其粘贴到mysql命令行中,并且运行正常),因此连接中出现错误(con->con类型为void * }施放到MYSQL *)。

SELECTUPDATE的其他功能正常。只有插入符号才会被破坏。

这是我的测试代码

#include <stdio.h>
#include <string.h>
#include <cquel.h>

int main(void)
{
    struct dbconn con = cq_new_connection("myurl.tld",
            "myuser", "mypasswd", "mydb");

    cq_init(1024, 128);

    char *fields[] = {
        "state",
        "parentID",
        "displayName"
    };

    char *vals[] = {
        "1",
        "19",
        "boop"
    };

    struct drow *row = cq_new_drow(3);
    cq_drow_set(row, vals);
    struct dlist *list = cq_new_dlist(3, fields, "");
    cq_dlist_add(list, row);

    cq_insert(con, "TaskType", list);
    cq_free_dlist(list);
    return 0;
}

插入函数

int cq_insert(struct dbconn con, const char *table, const struct dlist *list)
{
    int rc;
    char *query, *columns, *values;
    const char *fmt = "INSERT INTO %s(%s) VALUES(%s)";

    if (table == NULL)
        return 1;
    if (list == NULL)
        return 2;

    query = calloc(CQ_QLEN, sizeof(char));
    if (query == NULL)
        return -1;

    columns = calloc(CQ_QLEN/2, sizeof(char));
    if (columns == NULL) {
        free(query);
        return -2;
    }

    values = calloc(CQ_QLEN/2, sizeof(char));
    if (values == NULL) {
        free(query);
        free(columns);
        return -3;
    }

    rc = cq_dlist_fields_to_utf8(&con, columns, CQ_QLEN/2, *list);
    if (rc) {
        free(query);
        free(columns);
        free(values);
        return 100;
    }

    rc = cq_connect(&con);
    if (rc) {
        free(query);
        free(columns);
        free(values);
        return 200;
    }

    for (struct drow *r = list->first; r != NULL; r = r->next) {
        rc = cq_drow_to_utf8(&con, values, CQ_QLEN/2, *r);
        if (rc)
            break;

        rc = snprintf(query, CQ_QLEN, fmt, table, columns, values);
        if (CQ_QLEN <= (size_t) rc) {
            rc = -4;
            break;
        }

        rc = cq_query(&con, query);
        if (rc) {
            rc = 201;
            break;
        }
    }

    cq_close_connection(&con);
    free(query);
    free(columns);
    free(values);
    return rc;
}

和其中一个重要的辅助函数

int cq_fields_to_utf8(struct dbconn *con, char *buf, size_t buflen,
        size_t fieldc, char * const *fieldnames, bool usequotes)
{
    int rc = 0;
    size_t num_left = fieldc, written = 0;

    if (num_left == 0)
        return 1;

    char *temp = calloc(CQ_FMAXLEN+3, sizeof(char));
    if (NULL == temp)
        return -1;

    char *field = calloc((CQ_FMAXLEN+3)*2+1, sizeof(char));
    if (NULL == field) {
        free(temp);
        return -2;
    }

    /* prevent appending to buffer */
    buf[0] = '\0';

    cq_connect(con);
    for (size_t i = 0; i < fieldc; ++i) {
        bool escaped = fieldnames[i][0] == '\\';
        const char *orig = escaped ? &fieldnames[i][1] : fieldnames[i];
        const char *value;

        bool isstr = false;
        if (!escaped) {
            mysql_real_escape_string(con->con, field, orig, strlen(orig));
            value = field;
            if (usequotes)
                for (size_t j = 0; j < strlen(value); ++j) {
                    if (!isdigit(value[j])) {
                        isstr = true;
                        break;
                    }
                }
        } else {
            value = orig;
        }

        const char *a = isstr ? "'" : "";
        const char *c = --num_left > 0 ? "," : "";
        written += snprintf(temp, CQ_FMAXLEN+3, "%s%s%s%s", a, value, a, c);
        if (written >= buflen) {
            rc = 2;
            break;
        }

        strcat(buf, temp);
    }
    cq_close_connection(con);

    free(field);
    free(temp);
    return rc;
}
设置查询字符串时使用

1 个答案:

答案 0 :(得分:1)

找到我自己的问题。归咎于10分钟的规则。

我在cq_insert()看起来不够仔细,它正在进行双连接,关闭第二个连接,第一个丢失,指针指向释放的内存,所以是段错误。