Поврежденные массивы struct char - sqlite C ++ - PullRequest
0 голосов
/ 06 января 2020

Я немного озадачен этим. До сих пор все было хорошо с использованием SQLite, но сейчас я пытаюсь сохранить результаты моего запроса в простой структуре. Когда я делаю это в моем обратном вызове, все мои данные выглядят великолепно в моем векторе SQLItems, но как только завершается обратный вызов, мой вектор SQLItems, содержащий мои строки данных, внезапно повреждается. Есть идеи, что может быть причиной этого?

// Simple struct to hold column name and row data
struct SQLrow {
    char   * Column;
    char   * Data;
};

// static Vector to hold SQL rows
static std::vector<SQLrow>       SQLItems;

...
// static callback that handles placing query results into structs and into SQLItems vector
// SQLItems column/row data gets corrupted after this function exits
static int countTablesCallback(void *data, int count, char **rows, char **azColName) {
        int i;

        for (i = 0; i < count; i++) {
            SQLrow newItem = { azColName[i] ,rows[i] };
            SQLItems.push_back(newItem);
        }
        *static_cast<std::vector<SQLrow>*>(data) = SQLItems; // Tried this too but throws an exception 
        return 0;
    }

Я также подумал, что, возможно, возможно только статическое приведение из обратного вызова для сохранения вектора, но это также вызывает исключение. В тупик здесь. Спасибо за любой совет!

Ответы [ 3 ]

2 голосов
/ 06 января 2020

Ваш вектор в порядке, static_cast не имеет смысла, если только data фактически не используется в качестве параметра out. Ваша проблема, скорее всего, в том, что SQLrow содержит указатель на символ, а SQLite удаляет указанные строки после возврата обратного вызова. Изменение класса на

struct SQLrow {
    std::string Column;
    std::string Data;
};

должно решить проблему.

1 голос
/ 06 января 2020

Просто глядя на код, кажется, что данные, на которые указывает rows, будут признаны недействительными / уничтожены / изменены после возврата обратного вызова. Таким образом, вы не можете сохранить эти указатели для последующего использования, и вам придется сделать копию данных.

Один простой способ - изменить Column и Data с char * на std::string , В противном случае вам придется выполнить какое-то ручное управление памятью (выделите пространство с помощью new, а затем удалите его позже), что может привести к ошибкам и не рекомендуется в наши дни.

0 голосов
/ 09 января 2020

По моему мнению, очень мало случаев, когда вы хотите / должны использовать необработанную строку в c ++, и ваш не относится к таким. Кстати, я надеюсь, что это поможет вам или кому-то еще:

#include <vector>
#include <stdio.h>
#include <string.h>
#include <iostream>


struct SQLrow {
    char* Column;
    char* Data;
};

void your_callback(int count, char **rows, char **azColName) {

    std::vector<SQLrow> rows_list;

    for (int i = 0; i < count; i++) {

        /* Uncomment this if you want 
           your copy of the strings. If you
           use this, don't forget to free the
           memory yourself with delete[] s1 and
           s2.

        size_t s1_len = strlen(rows[i]);
        size_t s2_len = strlen(azColName[i]);

        char* s1 = new char [sizeof(char) * (s1_len + 1)];
        char* s2 = new char [sizeof(char) * (s2_len + 1)];

        memcpy(s1, rows[i], s1_len);
        s1[s1_len] = '\0';

        memcpy(s2, azColName[i], s2_len);
        s2[s2_len] = '\0';

        SQLrow r = { s1, s2 }; */

        SQLrow r = { rows[i], azColName[i] };

        rows_list.push_back(r);
    }

    // test the result
    for (int i = 0; i < count; i++) {
        SQLrow r = rows_list.at(i);

        std::cout << "rows:" << r.Column << " azColName:" << r.Data << std::endl;
    }
}

// this 2 lines are just for simulating the data
// you will get this 'warning: ISO C++ forbids converting a string constant to   char*''
char* rows[] = {"row1", "row2" , "row3" };
char* colName[] = {"name1", "name2", "name3" };

int main()
{
    your_callback(3, rows, colName);

    return 0;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...