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

Проблема с указателем C++/CLI = весело!

Я преобразовывал кучу старого кода C++ в код C++/CLI и думаю, что загнал себя в угол.

Моя цель состояла в том, чтобы взять неуправляемую библиотеку C++ и набор заголовочных файлов и предоставить их функциональность решению C#. Из чтения в Интернете стандартный способ сделать это:

  • Создайте два класса C++: один управляемый, другой неуправляемый.
  • Неуправляемый класс будет обрабатывать объекты в библиотеке C++, чтобы обеспечить желаемую функциональность.
  • Управляемый класс поместит все общедоступные методы в неуправляемый класс. Каждый метод-оболочка будет обрабатывать необходимые преобразования из String^ в строку и т. д.

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

Мой заголовочный файл выглядит так:

public ref class ManagedClass
{
public:
  ManagedClass();
  void CreateUnmanagedObject(String^ param1);
  void UseUnmanagedObject();

  UnmanagedObject *myUnmanagedObject;
}

И мой файл cpp выглядит так:

void ManagedClass::CreateUnmanagedObject(String^ param1)
{
   /* Convert params, use them in some way. */

   /* capture the output of this library call to the pointer defined in ManagedClass.*/
   myUnmanagedObject= &(LibrayObject.LibraryMethod1());  
}
void ManagedClass::UseUnManagedObject()
{
   /* This function will pass the Unmanaged object into
    * a library function which will do some work on it.
    */
   LibraryObject.LibraryMethod2(*myUnmanagedObject);
   /* Whoops! System.AccessViolationException is thrown! */
}

Интригует то, что если я вызову LibraryMethod2 в CreateUnmanagedObject сразу после LibraryMethod1, он будет работать нормально. Но после выхода CreateUnmanagedObject кажется, что память, на которую указывает myUnmanagedObject, потеряна.

Может ли кто-нибудь увидеть причину, по которой это происходит?

Изменить: объявления библиотеки выглядят так:

UnmanagedObject LibraryMethod1();
void LibraryMethod2(UnmanagedObject &param);
07.10.2010

  • Не могли бы вы опубликовать сигнатуры С++ библиотечных методов? 08.10.2010

Ответы:


1

Вы не берете адрес временной переменной? Если

LibraryObject.LibraryMethod1()

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

07.10.2010
  • У меня нет практики с С++. Если мне нужно взять адрес с помощью символа &, то это означает, что LibraryMethod1 возвращает мне значение, а не ссылку на объект, как я думал. Дох! 08.10.2010

  • 2

    Не уверен, в чем может быть ваша настоящая проблема, но все выглядит неправильно. Управляемая оболочка должна быть очень похожа на неуправляемую. Давайте работать с неуправляемым объявлением следующим образом:

    class Unmanagedclass {
    public:
        Unmanagedclass(const char* arg) {}
        void mumble() {}
    };
    

    Тогда ваша оболочка должна выглядеть так:

    #pragma managed(push, off)
    #include "unmanagedclass.h"
    #pragma managed(pop)
    
    using namespace System;
    using namespace System::Runtime::InteropServices;
    
    public ref class ManagedWrapper
    {
        Unmanagedclass* instance;
    public:
        ManagedWrapper(String^ arg) {
            IntPtr mem = Marshal::StringToCoTaskMemAnsi(arg);
            instance = new Unmanagedclass((char*)(void*)mem);
            Marshal::FreeCoTaskMem(mem);
        }
        ~ManagedWrapper() {
            delete instance;
            instance = 0;
        }
        !ManagedWrapper() {
            delete instance;
        }
        void mumble() {
            instance->mumble();
        }
    };
    

    Рецепт здесь в том, что экземпляр неуправляемого класса является указателем в оболочке. И просто делегируйте вызовы управляемых методов неуправляемым. Да, какая-то фигня со строками, как показано. И убедитесь, что этот собственный экземпляр будет удален, когда пользователь или сборщик мусора доберутся до него.

    07.10.2010
  • Хм, минус - это не совсем то, что я ожидал от этого поста. Хочешь объяснить, в чем проблема? 08.10.2010
  • @nobugz: +1. Поздравляю с достижением 100к. Тотальное господство :О 08.10.2010
  • Спасибо за пример кода. Это определенно то, что я должен был сделать с самого начала. 08.10.2010

  • 3

    Вы берете указатель на переменную в стеке temp. По чистой случайности он указывает на что-то, если вы вызываете методы один за другим.

    Я пишу что-то на С++ после многих лет комфорта на С# и должен сказать вам, что время от времени у меня возникают одни и те же проблемы.

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

    07.10.2010
    Новые материалы

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

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

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

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

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

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

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