string(..)kraszuje program, walka z stat/dyn link runtime'u

0

W pewnej klasie A mam metodę:

void setHost(std::string host) { _host = host; }

I wiele innych podobnych. _host jest zmienną prywatną. Następnie próbuję ją wywołać.

	A klasa;
	klasa.setHost("www.adres.prv.pl");

I w trybie debug wszystko jest ok. W trybie release kraszuje mi się program na tej linijce (klasa jest w DLL, którą do programu linkuję statycznie). Gdy wpiszę tam ten adres bez "www." wszystko jest ok, gdy wpiszę to www kraszuje się :(
O co chodzi?

0

Moim zdaniem problem jest gdzieś indziej. Odpal debugger i zobacz co sie dzieje.

0

brejkpojnt na tej lini i _host jest Bad Ptr.
W konstruktorze tej klasy ustawiam go _host = "";

Gdy nie ma www, na tym samym brejkpojncie _host jest taki jak go ustawilem ("").

0

Weź daj jakiś sensowny kawałek kodu, bo z tego i opisu ni *uja nic nie wynika. Gdzieś coś nadpisuje pointer albo coś podobnego - złapałeś może buffer oveflow w innym miejscu? Takie rzeczy lubią się niekiedy objawiać w mało oczywistych sytuacjach.

0

Tu nie ma co dawać bo to prosty kod jest. W nagłówku tej klasy mam napisaną tą metodę, w konstruktorze to co napisałem i to wszystko. Nigdzie więcej tej zmiennej nie używam.
Aha, no i dzieje się tak tylko jeśli w programie opcję runtime library mam ustawioną na multi-threaderd, na multi-threaded DLL jest OK, wyleciało mi to z głowy ;(, ale wolałbym statycznie linkować runtime.

0

Może w konstruktorze klasy A masz jakiś problem? Mi to też śmierdzi nadpisaniem czegoś w innym miejscu programu.

0

W ostateczności zrób minimalistyczną wersję wysypującego się programu i wrzuć gdzieś, najlepiej razem z pdb. Zobaczę czy to wina runtime'u. W sumie najlepiej byłoby wersję z wlinkowanym i zewnętrznym runtimem mieć i porównać zachowanie na niższym poziomie. Jeszcze lepiej by było gdyby po prostu były źródła...

0

No to lecą źródła.
eHTTPRequest.h

#pragma once

#ifdef EHTTP_EXPORTS
#define EHTTP_API __declspec(dllexport)
#else
#define EHTTP_API __declspec(dllimport)
#endif

#include "eHTTPContent.h"

#pragma warning( disable: 4251 )

class EHTTP_API eHTTPRequest
{
public:
	eHTTPRequest(void);
	~eHTTPRequest(void);

	void setHttpVersion(HTTP_Version httpVersion) { _httpVersion = httpVersion; }
	HTTP_Version getHTTPVersion() { return _httpVersion; }

	void setRequestType(RequestType requestType) { _requestType = requestType; }
	RequestType getRequestType() { return _requestType; }

	void setDocument(std::string document) { _document = document; }
	std::string getDocument() { return _document; }

	void setHost(std::string host) { _host = host; }
	std::string getHost() { return _host; }

	void setUserAgent(std::string userAgent) { _userAgent = userAgent; }
	std::string getUserAgent() { return _userAgent; }

	void setAccept(unsigned char accept) { _accept = accept; }

	void setAcceptLang(std::string acceptLang) { _acceptLang = acceptLang; }
	std::string getAcceptLang() { return _acceptLang; }

	void setAcceptLang(unsigned char acceptLang) { _acceptLangB = acceptLang; }

	void setAcceptCharset(unsigned char acceptCharset) { _acceptCharset = acceptCharset; }

	void setKeepAliveTime(int keepAliveTime) { _keepAliveTime = keepAliveTime; }
	int getKeepAliveTime() { return _keepAliveTime; }

	void setConnection(int connection) { _connection = connection; }

	void setReferer(std::string referer) { _referer = referer; }
	std::string getReferer() { return _referer; }

	void setContent(eHTTPContent content) { _content = content; }

	std::string getRequestString();	

private:
	HTTP_Version _httpVersion;
	RequestType _requestType;
	std::string _document;
	std::string _host;
	std::string _userAgent;
	std::string _referer;
	unsigned char _accept;
	std::string _acceptLang;
	unsigned char _acceptLangB;
	unsigned char _acceptCharset;
	int _keepAliveTime;
	unsigned char _connection;
	eHTTPContent _content;
};

eHTTPRequest.cpp

eHTTPRequest::eHTTPRequest(void)
{
	_document = "/";
	_acceptCharset = VNONE;
	_accept = VNONE;
	_acceptLangB = VNONE;
	_httpVersion = NONE;
	_acceptCharset = NONE;
	_acceptLang = NONE;
	_requestType = (RequestType)NONE;
	_host = "";
	_userAgent = "";
	_referer = "";
	_keepAliveTime = 0;
	_connection = NONE;
	_content = 0;
}
..........
..........
..........

main.cpp

#include <iostream>
#include <sstream>
#include <fstream>
#include "eHTTP.h"

using namespace std;

int main()
{
	eHTTPRequest req;
	req.setHost("www.adres.prv.pl");
	
	cin.get();

	return 0;
}

eHTTP.h includuje eHTTPRequest.h

dla wytrwałych disassembly z zaznaczoną linijką na której się wywala

77A6F9A9  add         eax,2Ch  
77A6F9AC  push        eax  
77A6F9AD  push        779C8D20h  
77A6F9B2  call        77A194A0  
77A6F9B7  pop         ecx  
77A6F9B8  jmp         77A6F9C4  
77A6F9BA  push        779C8D18h  
77A6F9BF  call        77A194A0  
77A6F9C4  mov         eax,dword ptr [ebp+0Ch]  
77A6F9C7  pop         ecx  
77A6F9C8  push        dword ptr [eax+28h]  
77A6F9CB  push        esi  
77A6F9CC  push        779CB1D6h  
77A6F9D1  jmp         77A6F974  
77A6F9D3  cmp         dword ptr [edi+4Ch],ebx  
77A6F9D6  je          77A6F9E8  
77A6F9D8  mov         al,byte ptr [esi+2]  
77A6F9DB  xor         al,byte ptr [esi+1]  
77A6F9DE  xor         al,byte ptr [esi]  
77A6F9E0  mov         byte ptr [esi+3],al  
77A6F9E3  mov         eax,dword ptr [edi+50h]  
77A6F9E6  xor         dword ptr [esi],eax  
77A6F9E8  mov         al,1  
77A6F9EA  pop         edi  
77A6F9EB  pop         esi  
77A6F9EC  pop         ebx  
77A6F9ED  leave  
77A6F9EE  ret         20h  
77A6F9F1  mov         eax,dword ptr fs:[00000018h]  
77A6F9F7  mov         eax,dword ptr [eax+30h]  
77A6F9FA  cmp         dword ptr [eax+0Ch],ebx  
77A6F9FD  je          77A6FA1F  
77A6F9FF  mov         eax,dword ptr fs:[00000018h]  
77A6FA05  mov         eax,dword ptr [eax+30h]  
77A6FA08  mov         eax,dword ptr [eax+0Ch]  
77A6FA0B  mov         eax,dword ptr [eax+0Ch]  
77A6FA0E  add         eax,2Ch  
77A6FA11  push        eax  
77A6FA12  push        779C8D20h  
77A6FA17  call        77A194A0  
77A6FA1C  pop         ecx  
77A6FA1D  jmp         77A6FA29  
77A6FA1F  push        779C8D18h  
77A6FA24  call        77A194A0  
77A6FA29  movzx       eax,word ptr [esi+4]  
77A6FA2D  pop         ecx  
77A6FA2E  movzx       ecx,word ptr [edi+54h]  
77A6FA32  xor         eax,ecx  
77A6FA34  push        eax  
77A6FA35  push        esi  
77A6FA36  push        779CB1A2h  
77A6FA3B  jmp         77A6F974  
77A6FA40  push        779C8D18h  
77A6FA45  call        77A194A0  
77A6FA4A  pop         ecx  
77A6FA4B  push        edi  
77A6FA4C  push        dword ptr [esi+2Ch]  
77A6FA4F  push        esi  
77A6FA50  push        779CB158h  
77A6FA55  call        77A194A0  
77A6FA5A  add         esp,10h  
77A6FA5D  jmp         77A6F8D3  
77A6FA62  mov         edi,dword ptr [ebp-20h]  
77A6FA65  cmp         dword ptr [esi+30h],edi  
77A6FA68  je          77A6F9E8  
77A6FA6E  mov         ecx,dword ptr fs:[18h]  
77A6FA75  mov         ecx,dword ptr [ecx+30h]  
77A6FA78  cmp         dword ptr [ecx+0Ch],eax  
77A6FA7B  je          77A6FA9D  
77A6FA7D  mov         eax,dword ptr fs:[00000018h]  
77A6FA83  mov         eax,dword ptr [eax+30h]  
77A6FA86  mov         eax,dword ptr [eax+0Ch]  
77A6FA89  mov         eax,dword ptr [eax+0Ch]  
77A6FA8C  add         eax,2Ch  
77A6FA8F  push        eax  
77A6FA90  push        779C8D20h  
77A6FA95  call        77A194A0  
77A6FA9A  pop         ecx  
77A6FA9B  jmp         77A6FAA7  
77A6FA9D  push        779C8D18h  
77A6FAA2  call        77A194A0  
77A6FAA7  pop         ecx  
77A6FAA8  push        edi  
77A6FAA9  push        dword ptr [esi+30h]  
77A6FAAC  push        esi  
77A6FAAD  push        779CB10Eh  
77A6FAB2  jmp         77A6FA55  
77A6FAB4  nop  
77A6FAB5  nop  
77A6FAB6  nop  
77A6FAB7  nop  
77A6FAB8  nop  
77A6FAB9  mov         edi,edi  
77A6FABB  push        ebp  
77A6FABC  mov         ebp,esp  
77A6FABE  mov         eax,dword ptr fs:[00000018h]  
77A6FAC4  mov         eax,dword ptr [eax+30h]  
77A6FAC7  cmp         byte ptr [eax+2],0  
77A6FACB  je          77A6FAE4  
77A6FACD  mov         eax,dword ptr [ebp+8]  
77A6FAD0  mov         byte ptr ds:[77AA8225h],1  
77A6FAD7  mov         dword ptr ds:[77AA8220h],eax  
77A6FADC  int         3    <------------------ !!!TUTAJ SIĘ WYWALA!!!  <------------------ !!!TUTAJ SIĘ WYWALA!!!
77A6FADD  mov         byte ptr ds:[77AA8225h],0  
77A6FAE4  pop         ebp  
77A6FAE5  ret         4  
77A6FAE8  nop  
77A6FAE9  nop  
77A6FAEA  nop  
77A6FAEB  nop  
77A6FAEC  nop  
77A6FAED  mov         edi,edi  
77A6FAEF  push        ebp  
77A6FAF0  mov         ebp,esp  
77A6FAF2  sub         esp,1Ch  
77A6FAF5  push        esi  
77A6FAF6  mov         esi,dword ptr [ebp+10h]  
77A6FAF9  push        edi  
77A6FAFA  xor         edi,edi  
77A6FAFC  cmp         esi,8  
77A6FAFF  ja          77A6FB54  
77A6FB01  mov         eax,dword ptr fs:[00000018h]  
77A6FB07  mov         eax,dword ptr [eax+30h]  
77A6FB0A  cmp         dword ptr [eax+0Ch],edi  
77A6FB0D  je          77A6FB2F  
77A6FB0F  mov         eax,dword ptr fs:[00000018h]  
77A6FB15  mov         eax,dword ptr [eax+30h]  
77A6FB18  mov         eax,dword ptr [eax+0Ch]  
77A6FB1B  mov         eax,dword ptr [eax+0Ch]  
77A6FB1E  add         eax,2Ch  
77A6FB21  push        eax  
77A6FB22  push        779C8D20h  
77A6FB27  call        77A194A0  
77A6FB2C  pop         ecx  
77A6FB2D  jmp         77A6FB39  
77A6FB2F  push        779C8D18h  
77A6FB34  call        77A194A0  
77A6FB39  pop         ecx  
77A6FB3A  push        esi  
77A6FB3B  push        779CB3AAh  
77A6FB40  call        77A194A0  
77A6FB45  pop         ecx  
77A6FB46  pop         ecx  
77A6FB47  push        edi  
77A6FB48  call        77A6FAB9  
77A6FB4D  xor         eax,eax  
77A6FB4F  jmp         77A6FD43  
77A6FB54  cmp         esi,dword ptr [ebp+14h]  
77A6FB57  jae         77A6FB9C  
77A6FB59  mov         eax,dword ptr fs:[00000018h]  
77A6FB5F  mov         eax,dword ptr [eax+30h]  
77A6FB62  cmp         dword ptr [eax+0Ch],edi  
77A6FB65  je          77A6FB87  
77A6FB67  mov         eax,dword ptr fs:[00000018h]  
77A6FB6D  mov         eax,dword ptr [eax+30h]  
77A6FB70  mov         eax,dword ptr [eax+0Ch]  
77A6FB73  mov         eax,dword ptr [eax+0Ch]  
77A6FB76  add         eax,2Ch  
77A6FB79  push        eax  
77A6FB7A  push        779C8D20h  
77A6FB7F  call        77A194A0  
77A6FB84  pop         ecx  
77A6FB85  jmp         77A6FB91  
77A6FB87  push        779C8D18h  
77A6FB8C  call        77A194A0  
77A6FB91  pop         ecx  
77A6FB92  push        dword ptr [ebp+14h]  
77A6FB95  push        779CB386h  
77A6FB9A  jmp         77A6FB40  
77A6FB9C  push        ebx  
77A6FB9D  mov         ebx,dword ptr [ebp+8]  
77A6FBA0  test        bl,1  
77A6FBA3  je          77A6FBF2  
77A6FBA5  cmp         dword ptr [ebp+18h],edi  
77A6FBA8  je          77A6FBF2 
0

Int3 to breakpoint. W każdym razie - jeżeli nie ma podpiętego debuggera to wyjątek nie jest generowany. Co to za biblioteka (nie mogę w tej chwili Windows 7 odpalić)? Wypadałoby rzucić okiem na callstack - skąd to jest wołane. Weź gdzieś tę binarkę wrzuć bo coś głupi jestem, nie widzę problemów...

0

Nie wspomniałeś, że używasz bety Visual C++ 2010...

0

Kiedyś tam mówiłem ;)

0

Mógłby ktoś wrzucić gdzieś kompilator i linker z VS 2008?

0

Tworzony jest tymczasowy string, bufor jest alokowany na 32 bajty, wypełniane jest wyłącznie 17, nic nie wychodzi ani przed ani za. Po przypisaniu wołany jest operator delete, który woła HeapFree, ten się pluje, że niewłaściwy adres, chociaż to adres otrzymany od HeapAlloc.

Wniosek jest jeden - któraś poprzednia alokacja musiała rozpieprzyć strukturę sterty, dlatego zwalnianie głupieje. Te Twoje klasy alokują coś wcześniej poprzez new i 'ręcznie' po tym grzebią?

0

Przez new to tylko inna klasa, ale jej w ogóle w tym kodzie nie używam.

A tak btw to jak to info wyciągnąłeś?

0

Debuggerem...

Stawiam, że konstruktor tamtej klasy coś psuje, nie chce mi się tego na ślepo analizować.

0
eHTTPContent::eHTTPContent(void)
{
	contentTab = new string[10];

	_paramsCount = -1;
	_contentLen = 0;
}

eHTTPContent::eHTTPContent(int maxConCount)
{
	if(maxConCount > 0)
		contentTab = new std::string[maxConCount];
	else contentTab = new string[10];

	_paramsCount = -1;
	_contentLen = 0;
}
0

Cholera, chcesz usłyszeć cieka nowinę? Zgłupiałem do reszty...

Pominąłem wywołanie konstruktora eHTTPRequest::eHTTPRequest w main, pominąłem std::assign, w efekcie zostało samo wywołanie eHTTPRequest::setHost(std::string) i zwolnienie bufora z tego stringa tymczasowego, wyjątek nadal występuje.

Albo masz jakieś obiekty statyczne, których konstrukcja coś miesza albo faktycznie ten string się [CIACH!]. Zaczynam faktycznie kompilator podejrzewać.

0

??

class EHTTP_API eHTTPRequest
{

 /*


  */
        unsigned char _connection;
        eHTTPContent _content;
};

eHTTPRequest::eHTTPRequest(void)
{

        _content = 0;
}
0

Hm, nie widzę inicjalizacji rzeczy statycznych poza tymi biblioteki standardowej. Biblioteka dll czysta, też nie jej wina. Musiałbym to dokładniej obejrzeć, ale program sprowadzony do main i wywołania metody obciętej do samego zwalniania tego tymczasowego stringa jak rzucało wyjątkiem tak rzuca. Weź zainstaluj Visual C++ 2008 EE i na nim kod przetestuj? Pamiętam, że sam jakieś przeboje z betą 2010 miałem a chwilowo mam ciekawsze rzeczy do roboty niż szukanie błędów w runtime'ie.

0

Dobra, olśniło mnie. Dziś w 'nieco kiepskim' stanie jestem... sorry za zamieszanie i niedopatrzenie.

Dobra, to teraz tak:

  • linkowanie statyczne ssie;
  • każda kopia runtime'u tworzy własną, oddzielną stertę;
  • runtime execa alokuje na swojej stercie, operator delete w dllce próbuje zwolnić ze swojej;
  • tutaj było moje niedopatrzenie - jedna sterta pod adresem 0x003D0000, druga pod 0x003C0000...
  • próba zwolnienia z niewłaściwej sterty == wyjątek.

Problem polega na tym, że statyczny runtime powinno się używać wyłącznie w samodzielnej aplikacji, nigdy tam, gdzie kilka modułów operuje na obiektach.

Jeszcze raz sorry za brak natychmiastowego, oczywistego wytłumaczenia.

0

Czyli rozwiązania są 2:
-linkować dynamicznie DLLkę
-linkować dynamicznie runtime
Tak?

0

Dynamiczne linkowanie DLLki rozwiązało sprawę, ale mam problem.

#include <iostream>
#include <sstream>
#include <fstream>
#include <Windows.h>
#include "eHTTP.h"

using namespace std;

int createEHTTPLib(eHTTP *ehttp, eHTTPRequest *request, eHTTPContent *content, int maxConCount = -1)
{
	HMODULE dll = LoadLibrary("eHTTP");
	if(dll != NULL)
	{
		eHTTPProc proc = NULL;
		eHTTPProcWithParam procWParam = NULL;

		proc = (eHTTPProc)GetProcAddress(dll, "createEHTTP");
		ehttp = (eHTTP*)proc();
		proc = NULL;
		proc = (eHTTPProc)GetProcAddress(dll, "createEHTTPRequest");
		request = (eHTTPRequest*)proc();
		proc = NULL;

		if(maxConCount > 0)
		{
			procWParam = (eHTTPProcWithParam)GetProcAddress(dll, "createEHTTPContentWithParam");
			content = (eHTTPContent*)procWParam(maxConCount);
		}
		else
		{
			proc = (eHTTPProc)GetProcAddress(dll, "createEHTTPContent");
			content = (eHTTPContent*)proc();
		}

	}
	else
	{
		cerr << "Could not open eHTTP.dll" << endl;
		return -1;
	}

	return 0;
}

int main()
{
	eHTTP *http = 0;
	eHTTPRequest *request = 0;
	eHTTPContent *content = 0;

	cout << createEHTTPLib(http, request, content);

	//http = 0;
	//HMODULE hDLL = LoadLibrary("eHTTP");
	//eHTTPProc proc = (eHTTPProc)GetProcAddress(hDLL, "createEHTTP");
	//http = (eHTTP*)proc();

	http->setHost("sadasd");

	cin.get();

	return 0;
}

Zakomentowany kod działa, i nie się nie kraszuje, ale kiedy chcę użyć tej funkcji znowu się kraszuje ;( WTF?

0

Dllkę możesz linkować statycznie, to znaczenia nie ma. Masz mieć runtime w dll, żeby był wspólny dla wszystkich modułów.

0

Ale jak statycznie zlinkowałem runtime i dynamicznie DLL (zakomentowanym kodem) to wsio działa OK.

0

Nie rozumiesz, runtime musi być 'cośtam dll', w obu projektach. Dlaczego? Ano dlatego, że wtedy oba korzystają z runtime'u w dllce, jest tylko jedna instancja runtime'u, jedna sterta używana przez standardowe alokatory C++ w każdym module korzystającym z runtime'u Visual C++ 2010. Jeżeli chociaż jeden moduł będzie miał runtime statycznie to wtedy będą dwie kopie, które nie będą mogły ze sobą współpracować - chociażby właśnie wspomniany problem ze stertą.

Jeszcze raz - chcesz żeby moduły ze sobą gadały poprawnie? Muszą mieć wspólny runtime. Mają mieć wspólny runtime? Muszą mieć runtime w wersji dll.

0

Ok, ok.

Zlinkuję ten runtime statycznie, ale tak czy owak, dlaczego mi nie działa ta funkcja?

0
hck napisał(a)

Zlinkuję ten runtime statycznie

WTF?

0

No dynamicznie, ofc.

1 użytkowników online, w tym zalogowanych: 0, gości: 1