Переменная-член C ++ не инициализирована - PullRequest
1 голос
/ 13 июля 2020

Мне было поручено сделать доступной базу кода C ++ для приложения. NET. Код C ++ используется в производственной среде в течение нескольких лет и работает без проблем.

Я упаковал код C ++ в dll и построил API на основе C, чтобы сделать его доступным для. NET через P /Invoke.

Если я тестирую API с помощью тестового приложения на основе C, все работает, как ожидалось. Если я тестирую API из приложения C#, приложение зависает. Во время отладки я обнаружил, что переменная-член C ++ просто не инициализируется, хотя код для ее инициализации выполняется.

Класс C ++ выглядит примерно так:

template<class T> class Product
{
    enum product_status
    {
        alpha,
        beta,
        production
    };

public:
    explicit Product(T& src) : source(&src), status(alpha) { }

    void bind(T& src) { source = &src; }
    
    void reset() 
    { 
        source->reset(); 
        status = alpha;
    }

private:
    Product(const Product<T>&);
    const Product<T>& operator = (const Product<T>&);

    T* source;
    product_status status;
};

Переменная типа Product объявляется в экспортированном методе C следующим образом:

void ProcessProduct(Type1* c1, Type2* c2)
{
    //
    // Do stuff
    //
    Product<Factory> p1(f1);
    //
    // Do stuff
    //
}

После выполнения строки выше переменная-член состояния в p1 все еще не инициализирована. Это происходит, только если API вызывается из. NET, если API вызывается из C тестового приложения, все инициализируется должным образом.

Метод ProcessProduct объявлен в C# следующим образом:

    [DllImport("product.dll", CallingConvention = CallingConvention.Cdecl)]
    static extern void ProcessProduct(IntPtr c1, IntPtr c2);

Мои знания C ++ базовые c, поэтому я не уверен, что мне не хватает. Я использую Visual Studio 2019 (16.6.3) на Windows 10. Проблема появляется в Debug x86, мне не нужно тестировать ее на x64.

Ответы [ 2 ]

1 голос
/ 18 июля 2020

Мне наконец удалось выяснить проблему и исправить ее.

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

После того, как я разработал API на основе C, я протестировал его с помощью приложения C, и он работал нормально. После этого я начал работать над приложением C#, и API начал вылетать или зависать. Вот что меня озадачило, API работал из приложения C, а не из C#. По правде говоря, я не тестировал повторно приложение C после того, как начал работать над частью C#. Проблема возникла из-за того, что я добавил директиву 'pragma pack' для отображения некоторой структуры из C в C#. Вместо того, чтобы добавлять его только для этих структур, я добавил его в файл заголовка, который был включен перед другими файлами заголовков, и эта директива pragma испортила кодовую базу C ++. По правде говоря, Visual Studio сгенерировала несколько предупреждений, связанных с несоответствиями пакетов прагм, но я изначально их проигнорировал.

0 голосов
/ 13 июля 2020

Некоторые стили могут исключать проблему, сначала make put product_status вне шаблона (не зависит от T), второе «перечисление классов» может устранить неоднозначность альфа (я не могу сказать, bul может существовать что-то еще, называемое альфа где-нибудь в вашем коде)

Вы можете «удалить» конструктор копирования и оператор присваивания.

Возможно, вы создаете нечто, называемое «классом обработчика», и если это так, если class - это «продукт», он должен возвращаться функцией фабрики, а не иметь указатель на нее. Попробуйте определить, можете ли вы использовать shered_ptr или unique_ptr вместо "Product"

https://godbolt.org/z/55c9TW

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...