Как текст в моем главном файле C ++ (в коде, который еще не был выполнен) может отображаться в строке? - PullRequest
0 голосов
/ 25 апреля 2011

Я новичок в C ++, поэтому многое из того, чего я не совсем понимаю, я пытаюсь сузить, как я получаю exc_bad_access, но мои попытки распечатать значения, кажется, усугубляют (или вызывают) проблему!

#include <iostream>
#include "SI_Term.h"
#include "LoadPrefabs.h"

int main() {
    SI_Term * velocity = new SI_Term(1, "m/s");
    std::cout<<"MAIN: FIRST UNITS "<<std::endl;
    velocity->unitSet()->displayUnits();
    return 0;
}

Приведенный выше код выдает ошибку (EXC_BAD_ACCESS) еще до появления строки std :: cout <<.Я проследил это с помощью xcode, и он не работает в вызове функции для нового SI_Term (1, "m / s"). </p>

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

НОВАЯ ИНФОРМАЦИЯ: Я сузил его до этого блока.Я должен объяснить, что этот блок пытается разложить набор физических единиц, записанных в формате кг * м / с ^ 2, и разделить его на кг, м, разделить на s * s.Когда что-то сломано, он использует LoadUnits (const char *) для чтения из файла.Я предполагаю (на данный момент правильно), что ни одна строка единиц не будет содержать где-либо около моего предела в 40 символов.

UnitSet * decomposeUnits(const char* setOfUnits){
    std::cout<<"Decomposing Units";
    int i = 0;
    bool divide = false;

    UnitSet * nextUnit = 0;
    UnitSet * temp = 0;
    UnitSet * resultingUnit = new UnitSet(0, 0, 0, 1);

    while (setOfUnits[i] != '\0') {
        int j = 0;
        char decomposedUnit[40];
        std::cout<<"Wiped unit."<<std::endl;
        while ((setOfUnits[i] != '\0') && (setOfUnits[i] != '*') && (setOfUnits[i] != '/') && (setOfUnits[i] != '^')) {
            std::cout<<"Adding: " << decomposedUnit[i]<<std::endl;
            decomposedUnit[j] = setOfUnits[i];
            ++i;
            ++j;
        }
        decomposedUnit[j] = '\0';
        nextUnit = LoadUnits(decomposedUnit);
        //The new unit has been loaded. now check for powers, if there is one read it, and apply it to the new unit.

        //if there is a power, read the power, read the sign of the power and flip divide = !divide
        if (setOfUnits[i] == '^') {
            //there is a power. Analize.
            ++i;++j;
            double power = atof(&setOfUnits[i]);
            temp = *nextUnit^power;
            delete nextUnit;
            nextUnit = temp;
            temp = 0;
        }
            //skip i and j till the next / or * symbol.
        while (setOfUnits[i] != '\0' && setOfUnits[i] != '*' && setOfUnits[i] != '/') {
            ++i; ++j;
        }

        temp = resultingUnit;

        if (divide) {
            resultingUnit = *temp / *nextUnit;
        } else {
            resultingUnit = *temp * *nextUnit;
        }
        delete temp;
        delete nextUnit;
        temp = 0;
        nextUnit = 0;

        // we just copied a word and setOfUnits[i] is the multiply or divide or power character for the next set.
        if (setOfUnits[i] == '/') {
            divide = true;
        }

        ++i;

    }
    return resultingUnit;
}

Ответы [ 3 ]

2 голосов
/ 25 апреля 2011

Я испытываю желание сказать, что SI_Term работает со стеком (или, может быть, уничтожает кучу). Вот отличный способ сделать это:

char buffer[16];
strcpy(buffer, "I'm writing too much into a buffer");

Ваша функция, вероятно, завершится, но затем нанесет ущерб. Проверьте все массивы в стеке и убедитесь, что вы не записываете за пределы.

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

1 голос
/ 25 апреля 2011

Здесь я удалил неважные вещи:

while (setOfUnits[i] != '\0') {
    while ((setOfUnits[i] != '\0') && (setOfUnits[i] != '*') && (setOfUnits[i] != '/') && (setOfUnits[i] != '^')) {
        ...
        ++i;
    }

    ...
    nextUnit = LoadUnits(decomposedUnit);

    ...
    if (...) {
        double power = ...;
        temp = *nextUnit^power;
        delete nextUnit;
    }

    ....
    temp = resultingUnit;
    delete temp;
    delete nextUnit;

    ...
    ++i;
}

Есть ряд проблем с этим:

  • Во внутреннем цикле вы увеличиваете i до setOfUnits[i] == '\0', конца строки. Затем вы снова увеличиваете i, за до конца строки.
  • nextUnit относится к типу UnitSet, который предположительно перегружает ^. Хотя возможно, что он перегружает его, чтобы означать «возведение в степень» , он, вероятно, этого не делает (а если и делает, то не должен): в языках на основе C, включая C ++, ^ означает XOR , не возведено в степень.
  • Вы удаляете указатели, возвращенные из других функций, то есть у вас есть функции, которые возвращают динамически распределенную память и ожидают, что вызывающая сторона delete этой памяти. Хотя это не является неправильным, и фактически является обычной практикой в ​​C, это считается плохой практикой в ​​C ++ Просто LoadUnits() верните UnitSet (а не UnitSet*) и убедитесь, что перегружены конструктор копирования и operator= в классе UnitSet. Если производительность становится проблемой, вы можете вернуть const UnitSet& или использовать умные указатели .
    Аналогичным образом вы размещаете и удаляете внутри одной и той же функции. В этом нет необходимости: просто сделайте resultingUnit выделенным стеком:

    UnitSet resultingUnit(0, 0, 0, 1);
    

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

Удачи!

1 голос
/ 25 апреля 2011

Вы упоминаете xcode, поэтому я предполагаю, что вы используете MAC.Тогда я бы посоветовал взглянуть на инструмент valgrind из http://valgrind.org/ Это проверка памяти, которая дает вам информацию, когда вы делаете что-то не так с памятью.Если ваша программа была собрана, включая символы отладки, она должна дать вам трассировку стека, которая поможет вам найти ошибку.

...