Поиск  Пользователи  Правила 
Закрыть
Логин:
Пароль:
Забыли свой пароль?
Войти
 
Страницы: 1
RSS
Память и Микрософт С компилятор...
 
Возникла проблема следующего плана: один кусок кода в различном контексте ведет себя по-разному (непредсказуемо):
Код
char c[]="666";
qConvert((char *)&c,3000000,&intKeyPos);

вызывает аксес вуалейшен (qConvert - ф-ция хор конвертирования, а intKeyPos - позиция ключа). НО:
Код
fsend((char *)&c,3000000);
...
void fsend(char* strSend,int intLen)
{
     int intSend=0;
     int i;
     
       qConvert(strSend,intLen, &intKe yPos);
...
Не дает такого эфекта, а приводит, как ни странно, к немедленному завершению программы (что помоему в винде вообще невозможно)... причем нет гарантии что в другом контексте это все не будет вести себя иначе...

Q:как такое возможно? и "что делать?"...
 
Ссылку на документацию по qConvert(), fsend() в студию!
 
Цитата
[TSS пишет:
Ссылку на документацию по qConvert(), fsend() в студию!
Да будет так...
где strNetKey - хор ключ, простая строка...
Код
void qConvert(char* buf,int intLen, int *intPos)
{
     int i=0;
     PVOID p=0;
     p=buf;
     
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for(i=0;i<intLen;i++)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;*(char*)p=*(char*)p^strNetKey [*intPos];
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;(*intPos)++;
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;p=(PVOID)((int)p+1);
 
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;if(strNetKey[*intPos]=='\0')*intPos=0;
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp ;  ;
}

Код
void fsend(char* strSend,int intLen)
{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int intSend=0;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int i;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;qConvert(strSend,intLen, &intKeyPos);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;while(intSend!=intLen)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;i=send(skMain,(char  *)(((int)strSend)+intSend),(intLen-intSend),0);
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;if (i==SOCKET_ERROR) goto error;
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;intSend+=i;
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;//MessageBox(0,(LPSTR)strSend,"",0);
 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;error:
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;MessageBox(wndLogin,(LPSTR)&strConnectionDropped ,(LPSTR)&strMainWndTitle,MB_ICONSTOP);
 
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;ExitProcess(0);
}
премудрость в чем - я не понимаю, как программа может просто завершится во втором представленном случае в моем первом посте... куда деется аксес вуалейшен...
 
А если брейкпойнты поставить и посмотреть где вылетает??? Раз вылетает, значит что-то с памятью, обращение нутеда! Да  и что значит вылетае, просто программа закрывается и надписи никакой?
 
:)... ню-ню...
как ты думаешь, почему задался я таким вопросом? дело в том, что прога пишется без RTL... какой тут брейкпоинт? с рантаймом то все работает :)... впрочем по этому вопросу решение уже найдено: дело в том, что функции работы со строками ядра винды lxxxxx, не учитывают, что может быть привышена выделенная ей память :) те:
Код
&nbsp;&nbsp;&nbsp;char c[0xF];
&nbsp;&nbsp;&nbsp;char s[]="Практикуй.................................";
&nbsp;&nbsp;&nbsp;lstrcpy((LPSTR)&c,(LPSTR)&s);

приводит к непредсказуемым последствиям...
 
Pharaoh, похоже вилы =)

qConvert((char *)&c,3000000,&intKeyPos);

В коде функции qConvert юзается сентенция "*(char*)p = *(char*)p ^ strNetKey[*intPos];", при этом intPos не инициализирована при вызове, и, скорее всего, содержит мусор (в DEBUG -- 0xСDСDСDСD, в RELEASE -- мусор со стека)

Кстати, по твоим sample-ам -- intKeyPos вообще нигде нет, вырезал эти блоки кода, или как ?
 
Цитата
Pharaoh пишет:
:)... ню-ню...
как ты думаешь, почему задался я таким вопросом? дело в том, что прога пишется без RTL... какой тут брейкпоинт? с рантаймом то все работает :)... впрочем по этому вопросу решение уже найдено: дело в том, что функции работы со строками ядра винды lxxxxx, не учитывают, что может быть привышена выделенная ей память :) те:
Код
&nbsp;&nbsp;&nbsp;char c[0xF];
&nbsp;&nbsp;&nbsp;char s[]="Практикуй.................................";
&nbsp;&nbsp;&nbsp;lstrcpy((LPSTR)&c,(LPSTR)&s);

приводит к непредсказуемым последствиям...

Естественно, а ты как думал ?
C/C++ не производит контроль на переполнение буфера -- это медицинсткий факт. Система (Win32 API), кстати, тоже. Там, правда, используются параметры вида dwBufferSize совместно с указателями на блоки памяти.
 
спасибо за совет...
это уже прекрасноо сам понял вчера, когда начал читать доки :)...
а с проблемой разбиратся не стал, просто переписал процедуры заново, теперь все греется нормально :)...
вобщем всеравно спасибо...

да, в связи с этим у меня появились новые вопросы относительно памяти: как _лучше_ (быстрее для выполнения и при небольших затратах оперативки) реализовать динамические строки? Куча или виртуальная память?... и, мне еще интересно КАК работают стандартные функции ртла, типа free(), принимая один параметр... как она знает сколько освобождать :)?

еще вопрос: есть куча, я получаю в ней скажем килобайт, потом первые три байта освобождаю, в памяти образуется дырка в три байта (что-то типа фрагментации)... что с ней делать и предусматривает ли это система при работе с кучей?
 
Цитата
Pharaoh пишет:
спасибо за совет...
это уже прекрасноо сам понял вчера, когда начал читать доки :)...
а с проблемой разбиратся не стал, просто переписал процедуры заново, теперь все греется нормально :)...
вобщем всеравно спасибо...
Не за что =)

Цитата
Pharaoh пишет:
да, в связи с этим у меня появились новые вопросы относительно памяти: как _лучше_ (быстрее для выполнения и при небольших затратах оперативки) реализовать динамические строки? Куча или виртуальная память?...
бысрее всего, имхо, hashtables, память выделять можно и стандартным malloc() -- работает достаточно эффективно. Если есть ограничения на размеры строк -- можно большими блоками с индексацией по N-байт
Цитата
Pharaoh пишет:
и, мне еще интересно КАК работают стандартные функции ртла, типа free(), принимая один параметр... как она знает сколько освобождать :)?
Смотри исходники библиотеки. Вкратце скажу -- если malloc вернул тебе адрес 0x12000020, то по адресу 0x12000000 находится структура с данными по этому блоку памяти =) Смещения и размеры не помню, но идею, думаю, поймешь =)[/QUOTE]

Цитата
Pharaoh пишет:
еще вопрос: есть куча, я получаю в ней скажем килобайт, потом первые три байта освобождаю, в памяти образуется дырка в три байта (что-то типа фрагментации)... что с ней делать и предусматривает ли это система при работе с кучей?
Это как это ты так делаешь ?
 
Цитата
TSS пишет:
бысрее всего, имхо, hashtables, память выделять можно и стандартным malloc() -- работает достаточно эффективно. Если есть ограничения на размеры строк -- можно большими блоками с индексацией по N-байт
hashtables, это что? я знаю только основу всей памяти - virtual memory, и производную от нее - heap... разве есть еще какая-то? если есть раскажи плз...
Цитата
TSS пишет:

Смотри исходники библиотеки. Вкратце скажу -- если malloc вернул тебе адрес 0x12000020, то по адресу 0x12000000 находится структура с данными по этому блоку памяти =) Смещения и размеры не помню, но идею, думаю, поймешь =)
ну вопервых, как я уже говорил, пишу без ртл, поэтому у меня нет маалока :) а есть только кернел винды... исходники которого я соответственно прочитать не могу... но это и не суть важно, мне просто стало интересно, как функции очистки памяти принемая в параметр поинтер на войд могут знать сколько убивать :)

Цитата
TSS пишет:
Цитата
Pharaoh пишет:
еще вопрос: есть куча, я получаю в ней скажем килобайт, потом первые три байта освобождаю, в памяти образуется дырка в три байта (что-то типа фрагментации)... что с ней делать и предусматривает ли это система при работе с кучей?
Это как это ты так делаешь ?
так:

void * pMemFirst=0;
void * pMemSecond=0;
pMemFirst=HeapAlloc(GetProcessHeap(),0,16);
pMemSecond=HeapAlloc(GetProcessHeap(),0,1024);
HeapFree(GetProcessHeap(),0,pMemFirst);

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

а, да и еще: если знаешь, подскажи плз, где выделяется память под переменные, объявленные стандартным образом, типа char c[1024], и можно ли ее как-то освободить?

зы: тебя трудно цитировать ;)...
 
Цитата
Pharaoh пишет:
hashtables, это что? я знаю только основу всей памяти - virtual memory, и производную от нее - heap... разве есть еще какая-то? если есть раскажи плз...
hastables -- это специальным образом организованный списки дынных, в которые каждому из элементов сопоставлен некий ключ. Очень удобно при string lookup (поиск строки в словаре например)
 
Цитата
Pharaoh пишет:
ну вопервых, как я уже говорил, пишу без ртл, поэтому у меня нет маалока :) а есть только кернел винды... исходники которого я соответственно прочитать не могу... но это и не суть важно, мне просто стало интересно, как функции очистки памяти принемая в параметр поинтер на войд могут знать сколько убивать :)
Там тот же принцип. Только организованно немного по-другому.
 
Цитата
Pharaoh пишет:
Цитата
TSS пишет:
Цитата
Pharaoh пишет:
еще вопрос: есть куча, я получаю в ней скажем килобайт, потом первые три байта освобождаю, в памяти образуется дырка в три байта (что-то типа фрагментации)... что с ней делать и предусматривает ли это система при работе с кучей?
Это как это ты так делаешь ?
так:

void * pMemFirst=0;
void * pMemSecond=0;
pMemFirst=HeapAlloc(GetProcessHeap(),0,16);
pMemSecond=HeapAlloc(GetProcessHeap(),0,1024);
HeapFree(GetProcessHeap(),0,pMemFirst);

по логике вещей, эти куски выделятся друг за другом... так?
по симу два вопроса: первый - что система будет делать с теми 16 байтами? второй - как система узнает, что удалить надо 16 байт, если я этого явно не говорю... она хранит данные о выделении в кучи гдето еще или как? затрудняюсь...
Система знает как и что удалять благодаря дескрипторам блоков -- структур с описухой, что, где и как было выделено / освобождено.
Есть HeapCompact() -- она "лепит" вместе все свободные блоки. Используемые не трогает.
 
Цитата
Pharaoh пишет:
а, да и еще: если знаешь, подскажи плз, где выделяется память под переменные, объявленные стандартным образом, типа char c[1024], и можно ли ее как-то освободить?

зы: тебя трудно цитировать ;)...

На стеке. Освобождение происходит после выхода из функции одной асмовой командой ret =)

зы: учел. разбил не несколько "подвопросов"
 
великое спасибо за информацию...

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

о стеке) а можно ли очистить всетаки вручную? или это уже потеряные байты... как я понял, стек - также производная от виртуальной памяти?

о хипе) не вкурсе, система сама вызывает HeapCompact? или мне надо это предусматривать? вообще хип весьма сложная и хило документированная вещь в сдк...

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

сори за такую кучу вопросов, просто впервые занялся написанием серьезного серверного приложения и понял, что простых переменных мне будет мало, вот и полез в глубины памяти винды... ведь охото все это порациональнее использовать :)

зы: :) извени что ввел в заблуждение, я не о том :) просто не сразу понял почему выдается каламбур при нажатии цитаты, потом пришел к выводу, что кавычки в твоем имени совпадают с символом тега... :)
 
Не беспокойся о том, что ты можешь за alloc'эйтить память, скажем 40Кб, а понадобится всего 2Кб. Там просто биты на страницах памяти устанавливаются, и когда происходит запись в страницу, ос выделяет память. Внёс небольшую лепту. Сам-то я мало знаю. Книга Джефри Рихтера - хорошая книга.
В стеке я думаю нельзя освободить, но может я и ошибаюсь.
Ос, что-то читал, что она сама вызывает HeapCompact, могу ошибаться. Хип нужен для того, чтобы, скажем, для переменной в 4 байта длинною целую страницу не выделять, а выделять по-чуть чуть из хипа, не теряя целую страницу на считанные байты.
 
Цитата
MishaSt пишет:
Не беспокойся о том, что ты можешь за alloc'эйтить память, скажем 40Кб, а понадобится всего 2Кб. Там просто биты на страницах памяти устанавливаются, и когда происходит запись в страницу, ос выделяет память. Внёс небольшую лепту. Сам-то я мало знаю. Книга Джефри Рихтера - хорошая книга.
В стеке я думаю нельзя освободить, но может я и ошибаюсь.
Ос, что-то читал, что она сама вызывает HeapCompact, могу ошибаться. Хип нужен для того, чтобы, скажем, для переменной в 4 байта длинною целую страницу не выделять, а выделять по-чуть чуть из хипа, не теряя целую страницу на считанные байты.
Не буду разбивать твой коммент.
По пунктам.

1) Jeffrey Richter's Advanced Windows -- библия программера Win32. Кто не согласен -- забаню =)
2) При HeapAlloc(40KB) выделяется именно 40KB CommittedMemory, ибо хип обычно треба как для performance. А вот в VirtualAlloc() можно и MEM_RESERVE юзать, правда это вещь в себе. При попадании на страницу с MEM_RESERVE генерится исключение, а это очень большая потеря в производительности (Page Faults -- помнишь ?)
3) Я что-то не припомню, что система сама вызывала HeapCompact() -- я нигде про это не читал.
 
Цитата
Pharaoh пишет:
великое спасибо за информацию...

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

о стеке) а можно ли очистить всетаки вручную? или это уже потеряные байты... как я понял, стек - также производная от виртуальной памяти?

о хипе) не вкурсе, система сама вызывает HeapCompact? или мне надо это предусматривать? вообще хип весьма сложная и хило документированная вещь в сдк...

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

сори за такую кучу вопросов, просто впервые занялся написанием серьезного серверного приложения и понял, что простых переменных мне будет мало, вот и полез в глубины памяти винды... ведь охото все это порациональнее использовать :)

зы: :) извени что ввел в заблуждение, я не о том :) просто не сразу понял почему выдается каламбур при нажатии цитаты, потом пришел к выводу, что кавычки в твоем имени совпадают с символом тега... :)

(о аллокейшене) -- обычно информационный блок идет перед выделенным. Про HeapAlloc() ничего сказать не могу -- не разбирался.

(о стеке) -- да. Только аккуратно -- втыкай asm-вставки.

(о хипе) -- доподлинно неизвестно. И вообще, HeapCompact() -- дело темное =)

(массивы) -- зачастую да. Например сделать хитрый хип, например для строк < 16, < 32, < 64, ... < 1024 байт и, в нем же > 1024. Код будет сложноват (немного =), но для '<' можно юзать уже табличную адресацию (т.е. по смещениям -- индексам) и иметь битовую карту "занято-не занято"

(зы) -- есть такое в движке форума =)
 
Великое вам спасибо за помощь...
пойду практиковать с накопленными сдесь знаниями... :)

нашел книгу, о которой вы говорите, оставляю линк, может кому поможет:  http://alexsoft.home.nov.ru/download/prog/Richter__2003_10_2 8.rar ...
если будут вопросы или узнаю что интересное, касательно менеджмента памяти - выкину сюда...

еще раз тхенкс...
Страницы: 1
Читают тему