информационная безопасность
без паники и всерьез
 подробно о проектеRambler's Top100
Все любят медЗа кого нас держат?Страшный баг в Windows
BugTraq.Ru
Русский BugTraq
 Анализ криптографических сетевых... 
 Модель надежности двухузлового... 
 Специальные марковские модели надежности... 
 Бэкдор в xz/liblzma, предназначенный... 
 Три миллиона электронных замков... 
 Doom на газонокосилках 
главная обзор RSN блог библиотека закон бред форум dnet о проекте
bugtraq.ru / форум / programming
Имя Пароль
ФОРУМ
если вы видите этот текст, отключите в настройках форума использование JavaScript
регистрация





Легенда:
  новое сообщение
  закрытая нитка
  новое сообщение
  в закрытой нитке
  старое сообщение
  • Напоминаю, что масса вопросов по функционированию форума снимается после прочтения его описания.
  • Новичкам также крайне полезно ознакомиться с данным документом.
Двойное разименование указателя при вызове функции Test? 15.06.09 01:40  Число просмотров: 3011
Автор: Den <Denis> Статус: The Elderman
Отредактировано 15.06.09 01:44  Количество правок: 1
<"чистая" ссылка>
Во втором параметре передаешь указатель на указатель?
<programming>
[C++] Вызов C++ из C# 04.06.09 18:18  
Автор: PS <PS> Статус: Elderman
<"чистая" ссылка>
Есть dll на C++, в ней функция, которую вызываю из C#
Получаю маленькую фигню с указателями.

Итак, в dll (C++) определена структура и ф-ия:
// Просто определяем структуру
class ST
{
public:
	char* ptr;
	int t;
};

DLLFORSHARP_API int Test(ST& st, char* ptr )
{
	ofstream of;
	of.open( "c:/testdll.txt" );

       // Выводим в файл указатель переданый в структуре, и указатель, переданый в стеке.
	stringstream ss2;
	ss2 << hex << (int)st.ptr << " " << (int)ptr;
	of << ss2.str().c_str() << endl;

       // Выводим строчку из структуры
	string s( st.ptr );	
	of << s.c_str() << endl;

        // Выводим строчку из стека
	string s2( ptr );	
	of << s2.c_str() << endl;

       // Для проверки выводим число
	stringstream ss;
	ss << st.t;
	of << ss.str().c_str();
	of.close();
	
	return s.size();
}

---

В тестовой програме на C# написан следующий код:
    struct ST
    {
        public byte[] ptr;
        public int t;
    };

    class Program
    {
        [DllImport("dllForSharp.dll")]
        public static extern int Test(ref ST param, byte[] param2);

        static void Main(string[] args)
        {
            string test = "kuku";
            ST st;
            st.ptr = System.Text.ASCIIEncoding.Default.GetBytes(test);
            st.t = 105;            

            // В структуре, и во втором параметре у нас один и тот же "указатель"
            Test(ref st, st.ptr);
        }

---

И получаем такой вот результат:
12c9ac0 15776c0

kuku
105

1. Число вывелось верно - структура передалась верно (ничего не съехало, байтики в нужной последовательности)
2. Строка kuku, переданая во втором параметре вывелась верно - byte[] вполне валидно можно рассматривать как сишный char*

3. Внимание вопрос: как оказалось, что st.ptr в структуре отлично от st.ptr во втором параметре ???
Внутри структуры это 12c9ac0, в в параметре 15776c0. Хотя передавал одно и то же:

st.ptr = System.Text.ASCIIEncoding.Default.GetBytes(test);
Test(ref st, st.ptr);

Пока никаких идей.
Двойное разименование указателя при вызове функции Test? 15.06.09 01:40  
Автор: Den <Denis> Статус: The Elderman
Отредактировано 15.06.09 01:44  Количество правок: 1
<"чистая" ссылка>
Во втором параметре передаешь указатель на указатель?
Почему указатель на указатель ??? 15.06.09 11:33  
Автор: PS <PS> Статус: Elderman
<"чистая" ссылка>
> Во втором параметре передаешь указатель на указатель?

class ST
{
public:
char* ptr;
...

DLLFORSHARP_API int Test(ST& st, char* ptr )
...

struct ST
{
public byte[] ptr;
...
public static extern int Test(ref ST param, byte[] param2);
...
ST st;
...
Test(ref st, st.ptr);
...

В C++ коде определяю char* ptr, в C# коде, аналогично, byte[] ptr.
Где здесь указатель на указатель в упор не вижу.
[C++] Возможно сборщик балуется 04.06.09 21:44  
Автор: amirul <Serge> Статус: The Elderman
Отредактировано 04.06.09 21:46  Количество правок: 1
<"чистая" ссылка>
> 3. Внимание вопрос: как оказалось, что st.ptr в структуре
> отлично от st.ptr во втором параметре ???
> Внутри структуры это 12c9ac0, в в параметре 15776c0. Хотя
> передавал одно и то же:

Насколько я помню у дотнета перемещающий GC (http://en.wikipedia.org/wiki/Generational_GC#Moving_vs._non-moving) и соответственно "указатель" на объект многократно меняется по ходу выполнения программы. В MC++ есть pin_ptr, который запрещает перемещать данный объект. В шарпе для этих целей есть fixed http://msdn.microsoft.com/en-us/library/f58wzh21(VS.80).aspx
Решение найдено 05.06.09 12:18  
Автор: PS <PS> Статус: Elderman
Отредактировано 05.06.09 12:25  Количество правок: 2
<"чистая" ссылка>
> Насколько я помню у дотнета перемещающий GC
> (http://en.wikipedia.org/wiki/Generational_GC#Moving_vs._no
> n-moving) и соответственно "указатель" на объект
> многократно меняется по ходу выполнения программы. В MC++
> есть pin_ptr, который запрещает перемещать данный объект. В
> шарпе для этих целей есть fixed
> http://msdn.microsoft.com/en-us/library/f58wzh21(VS.80).asp
> x

Идея задачи была такой: не использовать unsafe код, и в то же время дергать dll с указателями.
Получилось вот такое:
    struct ST
    {        
        public IntPtr ptr;
        public int t;
    };

    class Program
    {
        [DllImport("dllForSharp.dll")]
        public static extern int Test(ref ST param, IntPtr param2);

        static void Main(string[] args)
        {
            string test = "kuku";            
            byte[] b = System.Text.ASCIIEncoding.Default.GetBytes(test);                       

            ST st;
            st.ptr = Marshal.UnsafeAddrOfPinnedArrayElement(b, 0);
            st.t = 105;

            Test(ref st, st.ptr);            
        }

---

Разницы между первоначальным не работающим вариантом и этим:
1. byte[] заменен на IntPtr
2. Появилась "лишняя" операция
Marshal.UnsafeAddrOfPinnedArrayElement(b, 0);
Лишняя операция - боксинг/анбоксинг (или по умному маршалинг/анмаршалинг) - обычное дело в дот НЕТ 08.06.09 03:20  
Автор: void <Grebnev Valery> Статус: Elderman
<"чистая" ссылка>
COM / DCOM? 08.06.09 21:34  
Автор: Den <Denis> Статус: The Elderman
<"чистая" ссылка>
Да, все понятно, но что конкретно... 08.06.09 13:00  
Автор: PS <PS> Статус: Elderman
<"чистая" ссылка>
Решение задачи то найдено, но вопрос все равно остался - почему byte[] в стеке передается нормально, как указатель на область данных, а тот же byte[] в структуре - уже имеет совсем другое значение ?

Идея о GC мне кажется не совсем верной. Если бы она была верной, то сценарий был бы таким:
1. записали в стек один указатель
2. gc поменял адрес
3. записали в стек другой указатель
4. вызвали функцию
Таким образом вызывая функцию два раза подряд мы бы получили 4ре разных указателя.
Однако, по моим тестам видно, что указатель передающийся в структуре всегда один и тот же, и всегда отличный от указателя передающегося в параметре функции. Например, по первому вызову 12c9ac0, 15776c0, а при втором 12c9ac0, 15776f4.
Т.ч. gc, конечно меняет местоположение массива, но описанная проблема в чем то другом.
Такое впечатление что
F( byte[] ptr ) и struct S { byte[] ptr } - имеют различное внутреннее представление ptr, который указывает на одну и ту же область памяти. Видимо .net различает что есть что и "приводит" разные цифры в ptr к "одному знаменателю".
Это лишь предположение. Литературу по .net типа "windows" Рихтера мне найти еще не удалось.
1




Rambler's Top100
Рейтинг@Mail.ru


  Copyright © 2001-2024 Dmitry Leonov   Page build time: 0 s   Design: Vadim Derkach