Удаление указателей, которые были размещены в другой общей библиотеке - PullRequest
1 голос
/ 11 января 2011

ОБНОВЛЕНИЕ (решено): Хорошо, я полный идиот !Оказывается, в моей основной программе в разделе «делать вещи с данными» я увеличил указатель, поэтому удаление, очевидно, не сработало!D'oh!

Итак, я компилирую разделяемую библиотеку, которая имеет функцию, аналогичную этой (супер упрощенное представление), и эта библиотека также моя - поэтому я знаю, как распределяются данные:

// inside library

void* getData(int size) { // with other parameters

    UINT8* data = new UINT8[size];  // where typedef uint8_t  UINT8; for gcc

    // do a socket read, where data is the buffer
    blockingRead (someSocket, data, propertySize); 

    return (void*) data;
}

Он должен возвращать пустой указатель, так как данные могут быть структурой (так что можно просто привести к структуре).

Проблема в том, что я использую этот указатель в моей основной программе,и я хочу удалить его, когда я закончу.Если я сделаю это в своей основной программе:

// inside main program
char* data = (char*) Library::getData(5);
// do stuff with data

delete[] data; // crashes with:
// *** glibc detected *** core: free(): invalid pointer: 0x00002aaab007bca4 ***

Я подумал, может быть, мне следует вместо этого удалить ее из общей библиотеки:

// inside library

void disposeData(void* data) {  // call this from main program
    delete[] (UINT8*) data; // cast it back to the original type of pointer
}

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

Я, вероятно, делаю что-то глупое - пожалуйста, помогите мне найти ошибку в моих способах!

РЕДАКТИРОВАТЬ: Как указано в комментариях, кажется, что приведенный выше код работает - мне нужно будет посмотреть, что конкретно вызывает ошибки в моем коде.

Ответы [ 4 ]

2 голосов
/ 11 января 2011

Вы пробовали использовать valgrind ? Использование valgrind поможет вам определить широкий спектр ошибок управления памятью, которые, вероятно, являются причиной проблемы. Ошибка, которую вы видите, выглядит либо как повреждение кучи (как говорит @nos, возможно, в части do stuff), либо в том, что вы на самом деле не освобождаете тот же объект, который изначально выделяли.

0 голосов
/ 11 января 2011

Могу поспорить, что вы делаете что-то подобное, поскольку вы упоминаете «броски»:

#include <stdio.h>

class B { int x; };

class C { int y; };

class A : public B, public C { };

void* getData()
{
    A* a = new A();
    printf("%p\n", a);
    C* c = a;
    printf("%p\n", c);
    return c;
}

void deleteData(void* x)
{
    // delete (A*)x; // incorrect; causes crash
    delete (A*)(C*)x; // correct
}

int main()
{
    void* x = getData();
    deleteData(x);
    return 0;
}

Осторожно, компилятор может переводить то, что выглядит как невинное приведение в арифметику указателей за вашей спиной.

0 голосов
/ 11 января 2011

Как насчет использования более основанного на RAII дизайна, такого как умные указатели? Повышение умные указатели довольно хорошо разработаны.

0 голосов
/ 11 января 2011

Если библиотека предоставляет вам выделенные указатели, она должна объяснить, как их освободить.Он может предоставить свою собственную функцию для освобождения.Если у вас нет исходного кода для библиотеки и вы можете проверить, что он использует new[] для создания указателя, вы не можете быть уверены, как он распределяет память.Вероятно, вы столкнулись с тем, что ваш деллокатор не совпадает с его распределителем.

...