Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Глобал в DLL'ке

558
15 марта 2003 года
_ReZzZ_
14 / / 20.08.2000
Почему глобальная переменная в DLL'ке не сохраняет значения.

Пример:

В DLL'ке:

char* str;

void Func1()
{
str="String";
}

void Func2()
{
//здесь str уже не содержит ничего
}

Заранее благодарен.
380
21 марта 2003 года
Arestov
285 / / 20.09.2000
а тут дело не в DLL... а в языке Си, читаем Кернигана, Страуструпа и пр. в общем учим язык...

и думаем почему, ТАК всё работает, а у тебя нет:

int g_nValue = 0;

void Func1()
{
g_nValue = 555;
}

void Func2()
{
//здесь g_nValue всё ещё равна 555
}

........
// порядок вызовов
Func1();
Func2();
2.0K
22 марта 2003 года
Ignoramus
14 / / 21.10.2002
_ReZzZ_
Вы объявили указатель на char и проинициализировали его статической строкой, которая существует только в пределах Func1. После выхода из нее память, занимаемая этой строкой освобождается и на что будет указывать str - неизвестно.
Нужно сделать так:

char str[16];

void Func1(void)
{
::strcpy(str, "String");
}

Тогда заполнится глобальный буфер str, который доступен всем функциям в данном модуле.
3
23 марта 2003 года
Green
4.8K / / 20.01.2000
Цитата:
Originally posted by Ignoramus
_ReZzZ_
Вы объявили указатель на char и проинициализировали его статической строкой, которая существует только в пределах Func1. После выхода из нее память, занимаемая этой строкой освобождается и на что будет указывать str - неизвестно.
Нужно сделать так:

char str[16];

void Func1(void)
{
::strcpy(str, "String");
}

Тогда заполнится глобальный буфер str, который доступен всем функциям в данном модуле.



Ерунда. "String" будет иметь глобальную область видимости.
А стиль создавать статически строковые переменные с последующим копированием в них информации с помощью strcpy - это (IMHO) преступно ОПАСНО! либо используйте strncpy, либо выделяйте память динамически в соответствии с длинной принимаемой строки.

2.0K
23 марта 2003 года
Ignoramus
14 / / 21.10.2002
Цитата:
Originally posted by Green


Ерунда. "String" будет иметь глобальную область видимости.
А стиль создавать статически строковые переменные с последующим копированием в них информации с помощью strcpy - это (IMHO) преступно ОПАСНО! либо используйте strncpy, либо выделяйте память динамически в соответствии с длинной принимаемой строки.



Согласен, что статические массивы char имеют массу ограничений, в том числе необходимость контроля того, чтобы размер строки не превысил размер массива; я привел такой пример как простейший.
Что же касается "глобальной видимости", то тут позволю себе с Вами не согласиться.
Во-первых, с позиций формальной логики, если бы все было так, как Вы говорите, то у _ReZzZ_ не было бы проблемы. Во-вторых, все статические переменные, объявленные в любом блоке {} заканчивают свое существование после выхода из блока; и в-третьих, вообще некорректно говорить о "видимости" константы. Например, что можно сказать о "видимости" следующего кода:
void Func1(void)
{
1;
}
Как насчет "глобальной видимости" единицы? Или так:
void Func1(void)
{
int a = 1;
}
Единица глобально видна?

На самом деле константы, непосредственно включенные в код, в результирующем ассемблерном коде не берутся из памяти, как обычные переменные, а вводятся непосредственно из кода самой программы, например
MOV AX, 1
т.е. занести в регистр процессора сразу единицу, а не занести в регистр содержимое ячейки такой-то, как было бы для переменной. Поэтому как только исполнение программы выходит из функции, в ассемблерном коде которой содержится константа, то последняя никак уже использована быть не может, что и отражено в языке С.

3
24 марта 2003 года
Green
4.8K / / 20.01.2000
Цитата:
Originally posted by Ignoramus

Что же касается "глобальной видимости", то тут позволю себе с Вами не согласиться.
Во-первых, с позиций формальной логики, если бы все было так, как Вы говорите, то у _ReZzZ_ не было бы проблемы.



Просто, проблема не в этом.

Цитата:
Originally posted by Ignoramus

Во-вторых, все статические переменные, объявленные в любом блоке {} заканчивают свое существование после выхода из блока;



Именно ПЕРЕМЕННЫЕ, а не строковые литералы.

Цитата:
Originally posted by Ignoramus

и в-третьих, вообще некорректно говорить о "видимости" константы. Например, что можно сказать о "видимости" следующего кода:



Да, признаю, говоря про область видимости я допустил некоторую неточность в выражении своих мыслей, но суть остается неизменной:
"Память под строковые литералы выделяется статически, поэтому их свободно можно возвращать в качестве значения функции."
("Язык программирования С++", спец.издание, Б.Страуструп, п.5.2.2)

Цитата:
Originally posted by Ignoramus

void Func1(void)
{
1;
}
Как насчет "глобальной видимости" единицы? Или так:
void Func1(void)
{
int a = 1;
}
Единица глобально видна?

На самом деле константы, непосредственно включенные в код, в результирующем ассемблерном коде не берутся из памяти, как обычные переменные, а вводятся непосредственно из кода самой программы, например
MOV AX, 1
т.е. занести в регистр процессора сразу единицу, а не занести в регистр содержимое ячейки такой-то, как было бы для переменной. Поэтому как только исполнение программы выходит из функции, в ассемблерном коде которой содержится константа, то последняя никак уже использована быть не может, что и отражено в языке С.



Не совсем так. Вы путаете целые литералы и строковые литералы. В результирующем коде строковые литералы размещены в секции DATA (файлов PE-формата), а в исполняемом коде оперируют лишь указателями на эти данные, т.о. указатели можно копировать, возвращать в качестве значения ф-ции и т.д.

2.0K
24 марта 2003 года
Ignoramus
14 / / 21.10.2002
2 Green:
Эх, «Век живи - век учись», сказал поручик... Действительно, строковые литералы постоянно находятся в сегменте данных. Прошу прощения и беру свои слова обратно.
Спасибо, что поправили меня, Green ;)
Однако, _ReZzZ_ так и не получил ответа на свой вопрос ... :)
3.2K
26 марта 2003 года
bryk
20 / / 26.03.2003
Давайте по порядку.
Вот исходник dll:
-------- main.cpp --------
#include <stdio.h>

char *str;

void func1()
{
str = "Hello";
}

void func2()
{
printf("%s", str);
}
-------- end of main.cpp --------

-------- module.def --------
LIBRARY Module
EXPORTS
func1 @1
func2 @2
str @3
-------- end of module.def --------

Исходники использующего эту dll консольного приложения:
-------- main.cpp --------
#include <windows.h>
#include <stdio.h>

typedef void (*tfunc1)();
typedef void (*tfunc2)();

void main()
{
HMODULE dll;
tfunc1 func1;
tfunc2 func2;
char **str;

dll = LoadLibrary("..\\module\\debug\\module.dll");
if(!dll)
return;

func1 = (tfunc1)GetProcAddress(dll, "func1");
func2 = (tfunc1)GetProcAddress(dll, "func2");

str = (char**)GetProcAddress(dll, "str");

func1();
printf(*str);
func2();

}
-------- end of main.cpp --------

И всё работает. Hello никуда не исчезает.
Так писать можно и даже _нужно_.

оператор str = "Hello"; в функции func1 _ИНИЦИАЛИЗИРУЕТ_ указатель str адресом строки Hello, которая расположена в секции _констант_!

Удачи!
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог