Ошибка C при инициализации указателя на указатель

#c #arrays #pointers #dynamic #heap-memory

#c #массивы #указатели #динамический #куча-память

Вопрос:

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

При создании указателя на указатель (используемый как динамический массив указателей) я получаю ошибку где-то в куче, см. Изображение ниже для стека вызовов:

Ошибка

все setFrontNodes() является:

 void Node::setFrontNodes(int size) {
    frontNodes = new Node*[size]; // ERROR ON THIS LINE
    nFrontNodes = size;
}
  

Где заголовок для моего узла класса:

 class Node {
public:
    ~Node();
    int nBackNodes;
    int nFrontNodes;
    Node** backNodes;
    Node** frontNodes;
    void setFrontNodes(int size);
    void setBackNodes(int size);
    double value;
    double valuePrime;
    ActivationFunction* activationFunction = NULL;
    InitWeightMethod* initWeightMethod = NULL;
    void initWeights(double multiplier);
    double bias;
    double deltaBias;
    double* weights;
    double* deltaWeights;
    double errorGradient;
    Node(int number);
    void forwardProp();
    int number;
    string label;
    int layer;
};
  

Теперь вот странная проблема. Ошибка произойдет случайным образом. Я запущу ту же программу с теми же параметрами и всем остальным, и ошибка либо произойдет там, либо в другое время во время выполнения, либо вообще не произойдет! Это чрезвычайно затрудняет отслеживание ошибки и объясняет, почему у меня нет полного примера кода, который можно повторить.

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

Я запустил диагностику памяти, и при возникновении ошибки у меня все еще остается более 4 ГБ свободной оперативной памяти.

Спасибо за любое время! Дайте мне знать, если вам нужно что-нибудь еще, но, как я уже сказал, это большая программа, и ошибка появляется случайным образом, поэтому я ищу общую проблему, с которой я могу столкнуться при выделении памяти в куче, что вызывает ntdll.dll !Ошибка _RtlReportCriticalFailure@12() на скриншоте.

Комментарии:

1. Я вижу две возможности. Либо size это мусор, очень большое значение (возможно, неинициализированная переменная); или ваша программа повреждает кучу в другом месте, в коде, который не показан.

2. Я обновил новый снимок экрана, размер которого составляет всего 200, так что это не проблема. Итак, я, должно быть, повреждаю кучу в другом месте, есть ли у вас какие-либо ссылки или советы по этому поводу? Я программист-самоучка, настолько невежественный в некоторых вещах.

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

Ответ №1:

Как прокомментировал Игорь Тандетник, такого рода ошибки, вероятно, связаны либо с мусорным значением для size , либо с повреждением кучи. Убедитесь size , что это допустимое число, и убедитесь, что вы не записываете в память, к которой вы не должны прикасаться (так как это может повредить кучу).

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

Комментарии:

1. Спасибо за ответ, я проверю clang и valgrind. Я обновил вопрос новым скриншотом, который является более информативным, помогает ли это вообще? Он показывает, что size = 200, так что это не проблема, но как насчет адреса блока?

2. В этом случае место, где возникает ошибка, не является местом, где код нарушен. Код прерывается до этого момента, скорее всего, из-за повреждения кучи, и потребуется пройти гораздо больше кода, чтобы понять, где происходит повреждение кучи.

3. Такие инструменты, как valgrind и средства очистки адресов, могут проверять такие вещи, как повреждение кучи, и точно определять, где это происходит.

4. В вашей программе есть структуры данных, которые отслеживают выделенную память. Это куча. Когда эти структуры данных перезаписываются (обычно из-за неправильной записи или ошибки в коде), это вызывает повреждение кучи.

5. хм, я работаю над устранением ошибки, спасибо, теперь я знаю (вроде), что искать! Я бы хотел найти его сам, а не использовать программу, потому что я мог бы чему-то научиться.