Передача тройного указателя для выделения памяти в другой функции, исключение sscanf - PullRequest
1 голос
/ 22 декабря 2011

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

typedef float vector[3]

int mainLoaderFunc() {

    char* memory = NULL;
    size_t size = loadFile(fileName, &memory); // load model file into memory, this works, tested and true

    // create vector arrays
    vector *vertexArray = NULL;         
    vector *normalArray = NULL;         
    vector *textureArray = NULL;        

    loadArrays(size, memory, &vertexArray, &normalArray, &textureArray);

    // do other stuff with arrays

}

void loadArrays(size_t size, char *memory, vector **vertexArray, vector **normalArray, vector **textureArray) {

    int numVerts = 0; 
    int numNormals = 0;  
    int numTextures = 0;  

    char* p = memory;           // pointer to start of memory
    char* e = memory + size;    // pointer to end of memory

    // count verts, normals, textures for memory allocation
    while (p != e) {
        if (memcmp(p, "vn", 2) == 0) {
            numNormals++;
        } else if (memcmp(p, "vt", 2) == 0) { 
            numTextures++;
        } else if (memcmp(p, "v",  1) == 0) {
            numVerts++;
        } 
        while (*p++ != (char) 0x0A);
    }

    // allocate memory for vector arrays
    *vertexArray        = new vector[numVerts];
    *normalArray        = new vector[numNormals];
    *textureArray       = new vector[numTextures];

    p = memory;

    int vertexIndex = 0;
    int normalIndex = 0;
    int textureIndex = 0;  //*** IF BREAK POINT HERE: NO EXCEPTION

    // load data from memory into arrays
    while (p != e) {

        if (memcmp(p, "vn", 2) == 0) {
            sscanf(p, "vn %f %f %f", &normalArray[normalIndex][0], &normalArray[normalIndex][1], &normalArray[normalIndex][2]);
            normalIndex++;
        } else if (memcmp(p, "vt", 2) == 0) {
            sscanf(p, "vt %f %f", &textureArray[textureIndex][0], &textureArray[textureIndex][1]);
            textureIndex++;
        } else if (memcmp(p, "v", 1) == 0) {
            sscanf(p, "v %f %f %f", &vertexArray[vertexIndex][0], &vertexArray[vertexIndex][1], &vertexArray[vertexIndex][2]);
            vertexIndex++;
        } 
        while (*p++ != (char) 0x0A);
    }

}

Как только код попадает в часть sscanf, я получаю исключение:

Unhandled exception at 0x5e9cf2dc (msvcr100d.dll) in derp.exe: 0xC0000005: Access violation writing location 0xcccccccc.

Ответы [ 3 ]

2 голосов
/ 22 декабря 2011

Вы передаете недействительные адреса на sscanf. Посмотрите на один из аргументов вашей функции:

vector **vertexArray

vertexArray указывает на адрес указателя , переданного из mainLoaderFunc. *vertexArray относится к указателю на фактический массив vector, как вы понимаете, когда выделяете для него память:

*vertexArray = new vector[numVerts];

Следовательно, допустимый элемент в массиве будет:

(*vertexArray)[vertexIndex][0]

Обратите внимание на *, который отсутствует в вашем коде; *vertexArray относится к фактическому массиву. Теперь sscanf хочет получить адрес этой переменной, поэтому теперь получим ее адрес (для ясности добавлены дополнительные скобки):

&( (*vertexArray)[vertexIndex][0] )

Измените все ваши аргументы на sscanf, чтобы они были такими.

1 голос
/ 22 декабря 2011

Вы неправильно разыменовываете векторные указатели при передаче их на sscanf(). Попробуйте вместо этого:

if (memcmp(p, "vn", 2) == 0) { 
    sscanf(p, "vn %f %f %f", &((*normalArray)[normalIndex][0]), &((*normalArray)[normalIndex][1]), &((*normalArray)[normalIndex][2])); 
    ++normalIndex; 
} else if (memcmp(p, "vt", 2) == 0) { 
    sscanf(p, "vt %f %f", &((*textureArray)[textureIndex][0]), &((*textureArray)[textureIndex][1])); 
    ++textureIndex; 
} else if (memcmp(p, "v", 1) == 0) { 
    sscanf(p, "v %f %f %f", &((*vertexArray)[vertexIndex][0]), &((*vertexArray)[vertexIndex][1]), &((*vertexArray)[vertexIndex][2])); 
    ++vertexIndex; 
}  
1 голос
/ 22 декабря 2011

Как кто-то указал, вам действительно не следует использовать здесь тройные указатели.

Кроме того, вы можете захотеть выполнить сканирование файлов как что-то иное, чем цепочки if-блоков (или, по крайней мере, разделить его на части).в функции).

Это должно исправить вашу проблему, так как у вас есть только 2 разыменования, где у вас должно быть 3:

    if (memcmp(p, "vn", 2) == 0) {
        sscanf(p, "vn %f %f %f", &(*normalArray)[normalIndex][0], &(*normalArray)[normalIndex][1], &(*normalArray)[normalIndex][2]);
        normalIndex++;
    } else if (memcmp(p, "vt", 2) == 0) {
        sscanf(p, "vt %f %f", &(*textureArray)[textureIndex][0], &(*textureArray)[textureIndex][1]);
        textureIndex++;
    } else if (memcmp(p, "v", 1) == 0) {
        sscanf(p, "v %f %f %f", &(*vertexArray)[vertexIndex][0], &(*vertexArray)[vertexIndex][1], &(*vertexArray)[vertexIndex][2]);
        vertexIndex++;
    } 
...