Nano Hash - криптовалюты, майнинг, программирование

место чтения нарушения доступа 0x000000004

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

class_templet.h

typedef std::string QuestionName;
class ClassTemplete
{
public:
    ClassTemplete(Question iQuestionName);
private
    static std::map<QuestionName,ClassTemplete *> questionName_questionPointer_map_;
}

class_templet.cpp

map<QuestionName, ClassTemplete *> ClassTemplete::questionName_questionPointer_map_;

ClassTemplete::ClassTemplete(QuestionName iQuestionName)
{
    ClassTemplete::questionName_questionPointer_map_[iQuestionName] = this;
}

глава1_вопрос1.h

class C1Q1 : public ClassTemplete
{
public:
    C1Q1(QuestionName iQuestionName) : ClassTemplete(iQuestionName) {};
private:
    static QuestionName question_name_;
    static C1Q1 question_instance_;
}

глава1_вопрос1.cpp

QuestionName C1Q1::question_name_ = "C1Q1";
C1Q1 C1Q1::question_instance_(C1Q1::question_name_);

Я обнаружил, что проблема возникает в этом месте, когда я запускаю программу:

ClassTemplete::questionName_questionPointer_map_[iQuestionName] = this;

Однако я не могу объяснить, почему это происходит.

Пожалуйста, не стесняйтесь обращаться ко мне, если требуется дополнительная информация.

С уважением,

Yi Ji


  • Похоже, что ClassTemplete::questionName_questionPointer_map_ не инициализирован или инициализирован значением NULL, а индексация массива на этой недопустимой карте заставляет вас пытаться сохранить что-то в 0x000...4 03.11.2013
  • Вы пытались разыменовать нулевой указатель. 03.11.2013
  • На самом деле, чем больше я об этом думаю, это звучит как проблема инициализации синглтона, определенного в другой единице перевода (class_templet.cpp). Это неправильный способ использования синглтона, методы доступа, которые их обертывают, - это путь. 03.11.2013

Ответы:


1

Где находится QuestionName C1Q1:::question_name_ относительно ClassTemplate::questionName_questionPointer_map_? Похоже, что обе переменные имеют статическую продолжительность хранения, т. е. они создаются до запуска main(). Однако компилятор/компоновщик C++ заказывает создание таких глобальных объектов только с одной единицей трансляции (в этом случае объекты создаются сверху вниз), а не между единицами трансляции (в этом случае объекты создаются в случайном порядке).

Ваша проблема выглядит так, как будто ClassTemplate::questionName_questionPointer_map будет построен после C1Q1::question_name_. То есть, когда создается C1Q1::question_name_, осуществляется доступ к объекту, который еще не создан.

Обычное исправление заключается в том, чтобы сделать объект static зависимым от других объектов, не от объекта, а скорее от функции с локальной переменной static, на которую возвращается ссылка:

std::map<QuestionName,ClassTemplete *>&
ClassTemplete::questionName_questionPointer_map_() {
    static std::map<QuestionName,ClassTemplete *> rc;
    return rc;
}

(обратите внимание, что эта конструкция не является потокобезопасной, если вы не используете C++11; она обеспечивает многопоточность при использовании C++11).

02.11.2013
  • +1, и я хотел бы добавить еще один за то время, которое потребовалось, чтобы разобрать это. Как всегда, отличная работа, сэр. 03.11.2013
  • @WhozCraig: Спасибо. Я думаю, что именно эту проблему я видел достаточно часто, т.е. мне просто нужно было подтвердить соответствующие признаки (глобальные объекты, зависящие друг от друга). 03.11.2013
  • @DietmarKühl Большое спасибо, ваше решение работает, когда я возвращаю ссылку на локальную статическую переменную. Тем не менее, я блуждаю, если есть решение использовать статическую переменную questionName_questionPointer_map_ ClassTemplate в этом случае. Если я использую локальную статическую переменную, та, которую я определил ранее, менее чем бесполезна. :) 03.11.2013

  • 2

    Вы должны использовать std::map::insert, вы не можете использовать ClassTemplete::questionName_questionPointer_map_[iQuestionName] = this; при вставке нового ключа в карту.

    Этот код должен работать:

    ClassTemplete::questionName_questionPointer_map_.insert(std::make_pair(iQuestionName, this));
    
    02.11.2013
    Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

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

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..