The way you check for bad pointers on Win32 is by calling the IsBadReadPtr and IsBadWritePtr API. Michael Howard calls these APIs “CrashMyApplication” and “CorruptMemoryAndCrashMySystem” respectively. The problem with IsBadReadPtr/IsBadWritePtr is that they do exactly what they’re advertised as doing: They read and/or write to the memory location specified, with an exception handler wrapped around the read/write. If an exception is thrown, they fail, if not, they succeed.
There are two problems with this. The only thing that IsBadReadPtr/IsBadWritePtr verifies is that at the instant that the API is called, there was valid memory at that location. There’s nothing to prevent another thread in the application from unmapping the virtual address passed into IsBadReadPtr immediately after the call is made. Which means that any error checks you made based on the results of this API aren’t valid (this is called out in the documentation for IsBadWritePtr/IsBadReadPtr).
The other one is worse. What happens if the memory address passed into IsBadReadPtr is a stack guard page (a guard page is a page kept at the bottom of the stack – when the system top level exception handler sees a fault on a guard page, it will grow the threads stack (up to the threads stack limit))? Well, the IsBadReadPtr will catch the guard page exception and will handle it (because IsBadReadPtr handles all exceptions). So the system exception handler doesn’t see the exception. Which means that when that thread later runs, its stack won’t grow past the current limit. By calling IsBadReadPtr in your API, you’ve turned an easily identifiable application bug into a really subtle stack overflow bug that may not be encountered for many minutes (or hours) later.
PD>Свое решение не привожу, интересно, кто что скажет.
такой вопрос, а возможно на паскале сделать функцию StrCmp которую экспортировать, для дальнейшего использования в C? тогда отпадет вообще надобность о знании внутреннем устройстве стороки Фортрана...
Проблема банальна, решения точного не существует. Меня интересует, кто что думает о лучшем решении.
В функцию передается указатель char*. Он показывает на строку, но она может быть не закончена нулем. Ничего не поделаешь — строка передается из Фортрана, там это не обязательно. Она не может внутри себя иметь пробелов и может их иметь в конце (но может не иметь). Если пробелы в конце есть — первый из них рассматривается как конец строки.
Эту строку надо сравнить с массивом других и найти равную.
Ясно, что точного решения нет, но что лучше всего сделать ?
Изменения в строке делать нельзя (например) искать пробел и встроить на его место ноль), так как строка может храниться на странице read-only. Копировать можно, но опять-таки где ее конец — сказать трудно.
Свое решение не привожу, интересно, кто что скажет.
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Уважаемый Олл!
PD>Проблема банальна, решения точного не существует. Меня интересует, кто что думает о лучшем решении.
PD>В функцию передается указатель char*. Он показывает на строку, но она может быть не закончена нулем. Ничего не поделаешь — строка передается из Фортрана, там это не обязательно. Она не может внутри себя иметь пробелов и может их иметь в конце (но может не иметь). Если пробелы в конце есть — первый из них рассматривается как конец строки.
PD>Эту строку надо сравнить с массивом других и найти равную.
PD>Ясно, что точного решения нет, но что лучше всего сделать ?
PD>Изменения в строке делать нельзя (например) искать пробел и встроить на его место ноль), так как строка может храниться на странице read-only. Копировать можно, но опять-таки где ее конец — сказать трудно.
PD>Свое решение не привожу, интересно, кто что скажет.
//попробуем угадать максимальный размер строкиchar stringCopy[MAX_STRING_SIZE];
//в принципе, здесь можно сначала проверить имею-ли я доступ к этому куску памяти...
memcpy(&stringCopy[0],srcString,MAX_STRING_SIZE-1);
stringCopy[MAX_STRING_SIZE-1] = 0;
// а потом еще проверяем на пробелы, ну и т.д.
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>В функцию передается указатель char*. Он показывает на строку, но она может быть не закончена нулем. Ничего не поделаешь — строка передается из Фортрана, там это не обязательно. Она не может внутри себя иметь пробелов и может их иметь в конце (но может не иметь). Если пробелы в конце есть — первый из них рассматривается как конец строки.
PD>Эту строку надо сравнить с массивом других и найти равную. PD>Ясно, что точного решения нет, но что лучше всего сделать ?
PD>Изменения в строке делать нельзя (например) искать пробел и встроить на его место ноль), так как строка может храниться на странице read-only. Копировать можно, но опять-таки где ее конец — сказать трудно.
А изменить код можно? Чтобы он передавал в C — функцию char* и длину строки?
PD>Эту строку надо сравнить с массивом других и найти равную.
PD>Ясно, что точного решения нет, но что лучше всего сделать ?
Первое, что приходит в голову — нужно определить длину строки, например, поискать закономерности в символах поступающих в строку. Если брать сам алгоритм, то производить проверки до первого пробела или до первого некорректного символа, или до первого нуля, или до завершения известной строки. Получится от нуля до n строк. Если n, то наверное включить генератор случайных чисел .
Здравствуйте, ssm, Вы писали:
ssm>такой вопрос, а возможно на паскале сделать функцию StrCmp которую экспортировать, для дальнейшего использования в C? тогда отпадет вообще надобность о знании внутреннем устройстве стороки Фортрана...
Когда-то давно смотрел, как устроены строки в MS Fortran 5.0. Компилятор брал константу из объявления строки и везде в дальнейшем подставлял непосредственное значение. Я, когда подобное делал, знал, как объявлены строки в Фортране, поэтому такой проблемы у меня не возникало. Если был доступен исходник Фортран-программы, объявлял строку как С-строку, тогда к ней добавлялся 0 в конце. Правда, я и сейчас не знаю, вошло ли это в стандарт Фортрана.
AFAIK, в строках Паскаля длина хранится в начале строки. И потом, использовать еще один язык, imho, лишнее.
Re: char*
От:
Аноним
Дата:
04.04.05 11:06
Оценка:
PD>В функцию передается указатель char*. Он показывает на строку, но она может быть не закончена нулем. Ничего не поделаешь — строка передается из Фортрана, там это не обязательно.
А разве в Фортране строки заканчиваются не на '$' ?
Pavel Dvorkin wrote:
> В функцию передается указатель char*. Он показывает на строку, но она может быть не закончена нулем. Ничего не поделаешь — строка передается из Фортрана, там это не обязательно. Она не может внутри себя иметь пробелов и может их иметь в конце (но может не иметь). Если пробелы в конце есть — первый из них рассматривается как конец строки.
А если нет пробелов в конце? Как гарантированно определить конец строки?
ssm>это была описка по поводу паскаля, я имел в виду Фортран
Да, я увидел твою поправку после того, как отправил свой пост. В Фортране, AFAIR, есть функция LEN, возвращающая длину строки. Проблема в том, что возвращает она объявленную, а не фактическую длину. Откровенно говоря, не помню, что происходит при перезаписи в строку, мусор с прошлого раза, imho, не остается. Как-нибудь этим воспользоваться. Но максимальную длину знать не помешает.
Re: char*
От:
Аноним
Дата:
04.04.05 12:37
Оценка:
менять надо....
Одно можно сказать уверенно.
Осторожнее с этой "библиотекой" на фортране, если уж такая оплошность вылезла тогда сложно даже догадаться что там еще есть.
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Уважаемый Олл!
PD>Проблема банальна, решения точного не существует. Меня интересует, кто что думает о лучшем решении.
PD>В функцию передается указатель char*. Он показывает на строку, но она может быть не закончена нулем. Ничего не поделаешь — строка передается из Фортрана, там это не обязательно. Она не может внутри себя иметь пробелов и может их иметь в конце (но может не иметь). Если пробелы в конце есть — первый из них рассматривается как конец строки.
PD>Эту строку надо сравнить с массивом других и найти равную.
PD>Ясно, что точного решения нет, но что лучше всего сделать ?
PD>Изменения в строке делать нельзя (например) искать пробел и встроить на его место ноль), так как строка может храниться на странице read-only. Копировать можно, но опять-таки где ее конец — сказать трудно.
PD>Свое решение не привожу, интересно, кто что скажет.
Здравствуйте, rus blood, Вы писали:
RB>Здравствуйте, Pavel Dvorkin, Вы писали:
RB>Передать вместе со строкой ее длину, конечно, нельзя?
Хе-хе... Иногда она передается сама, хоть я и не просил — если пытаюсь возвращать из C функции строку. В этом случае возвращаемая строка в С функции оказывается в виде двух ВХОДНЫХ параметров — строка и длина. Я сегодня соорудил такую функцию, у нее в С 4 аргумента, а в Фортране — 2
А в обычном случае — не передается. И передать сам не могу, т.к. не знаю, а знал бы — не хочу.
Здравствуйте, Privalov, Вы писали:
P>Здравствуйте, ssm, Вы писали:
P>Когда-то давно смотрел, как устроены строки в MS Fortran 5.0. Компилятор брал константу из объявления строки и везде в дальнейшем подставлял непосредственное значение. Я, когда подобное делал, знал, как объявлены строки в Фортране, поэтому такой проблемы у меня не возникало. Если был доступен исходник Фортран-программы, объявлял строку как С-строку, тогда к ней добавлялся 0 в конце. Правда, я и сейчас не знаю, вошло ли это в стандарт Фортрана.
Да, это я и делаю. Но вдруг юзер забудет добавить C в конце...
SL>char stringCopy[MAX_STRING_SIZE];
SL>//в принципе, здесь можно сначала проверить имею-ли я доступ к этому куску памяти...
SL>memcpy(&stringCopy[0],srcString,MAX_STRING_SIZE-1);
Здесь и на AV недолго нарваться... Откуда ты знаешь, что из srcString можно копировать MAX_STRING_SIZE-1 ?
zuv>Первое, что приходит в голову — нужно определить длину строки, например, поискать закономерности в символах поступающих в строку. Если брать сам алгоритм, то производить проверки до первого пробела или до первого некорректного символа, или до первого нуля,
Здравствуйте, Аноним, Вы писали:
PD>>В функцию передается указатель char*. Он показывает на строку, но она может быть не закончена нулем. Ничего не поделаешь — строка передается из Фортрана, там это не обязательно.
А>А разве в Фортране строки заканчиваются не на '$' ?
Это в Бейсике ИМЕНА текстовых переменных заканчиваются $
Здравствуйте, Аноним, Вы писали:
А>менять надо....
что или кого ?
А>Одно можно сказать уверенно. А>Осторожнее с этой "библиотекой" на фортране, если уж такая оплошность вылезла тогда сложно даже догадаться что там еще есть.
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>В Форране есть строки с нулем PD>CHARACTER*10 STR PD>STR= 'ABC'C PD>Но пользователь может C забыть PD>Изменять ее в Фортране нельзя — не могу я требовать от пользователя, чтобы он каждую строку в специальную функцию передавал PD>CALL SUB('TEST STRING'C) PD>имеет право и будет нормально PD>CALL SUB('TEST STRING) PD>может привести к проблеме
Насколько я знаю, в Фортране, когда передаёшь строку в функцию, как последний скрытый параметр передаётся максимальная длина этой строки. То есть, если мы делаем интерфейс между Фортран и C мы должны сишную функцию принимающую фортрановскую строку объявлять так:
void SUB(char*, unsigned)
иначе не скомпилится. правильно я понимаю?
А вот что будет при CALL SUB('TEST STRING'C), будет ли скрытый параметр?
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Здравствуйте, SergeyL, Вы писали:
SL>>char stringCopy[MAX_STRING_SIZE];
SL>>//в принципе, здесь можно сначала проверить имею-ли я доступ к этому куску памяти...
SL>>memcpy(&stringCopy[0],srcString,MAX_STRING_SIZE-1);
PD>Здесь и на AV недолго нарваться... Откуда ты знаешь, что из srcString можно копировать MAX_STRING_SIZE-1 ?
//в принципе, здесь можно сначала проверить имею-ли я доступ к этому куску памяти...
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Здравствуйте, korzhik, Вы писали:
K>>А изменить код можно? Чтобы он передавал в C — функцию char* и длину строки?
PD>В Форране есть строки с нулем
PD>CHARACTER*10 STR
PD>STR= 'ABC'C
PD>Но пользователь может C забыть
K>Насколько я знаю, в Фортране, когда передаёшь строку в функцию, как последний скрытый параметр передаётся максимальная длина этой строки. То есть, если мы делаем интерфейс между Фортран и C мы должны сишную функцию принимающую фортрановскую строку объявлять так: K>
K> void SUB(char*, unsigned)
K>
K>иначе не скомпилится. правильно я понимаю?
Скомпилируется что угодно, работать не будет.
Если в фортране функция описана как имеющая С интерфейс, это не делается.