Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / C++ [игнор отключен] [закрыт для гостей] / Проблемы с памятью при работе с базой данных / 15 сообщений из 15, страница 1 из 1
28.11.2003, 21:09
    #32338297
grifon
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Проблемы с памятью при работе с базой данных
Господа, прошу руку помощи. Уже просто замучался. Проблема в следующем: нужно из базы сделать выборку (из двух таблиц), В принципе все работает, НО после выполнения pICommandText->Execute исчезает примерно около полумегабайта памяти. Таблица Clients занимает тоже около того, а DocNum - в принципе маленькая (строк 15 пока). Т.е. по идее результат запроса должен занимать несколько килобайт. Так вот даже после выполнения всех Release() память не возвращается :( Помогите решить проблему. Куда девается память?

Вот код:
...
wsprintf(sqlQuery, L"SELECT DocNum, Name FROM Clients AS Cl, DocHeads AS DH WHERE DH.ClientID = Cl.ExternalID");

pICommandText->SetCommandText(DBGUID_DBSQL, sqlQuery);
pICommandText->Execute(NULL, IID_IRowset, NULL, NULL, (IUnknown**) &pIRowset);
сразу после этого оператора уходит ~500 Kb памяти, даже если таблица DocNum совсем пустая (т.е. результат должен быть нулевой ...)
...
...
Рейтинг: 0 / 0
29.11.2003, 12:55
    #32338416
Случайный прохожий
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Проблемы с памятью при работе с базой данных
В каком программном продукте работаете?
...
Рейтинг: 0 / 0
29.11.2003, 14:02
    #32338436
grifon
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Проблемы с памятью при работе с базой данных
Visual C++ правда под КПК, но я думаю, особо разницы нет...
Насколько я понял, там SQL Server забирает всю доступную память, пока не съест все целиком, а потом просто прога вылетает при очередном запросе.
И если я правильно понимаю суть, надо ограничить память доступную для SQL Server'a...
...
Рейтинг: 0 / 0
29.11.2003, 14:46
    #32338445
DJStealth
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Проблемы с памятью при работе с базой данных
grifon писал:И если я правильно понимаю суть, надо ограничить память доступную для SQL Server'a...
В SQL Enterprise Manager свойства сервера(если у тебя есть права админа) закладка Memory
Поставь крыжик вместо Dynamically configure SQL Server memory
на Use a fixed memory size
или там же можешь просто задать макимальный размер
а вообще то укажи для коннектора (который к серваку подключается)pICommandText
m_ptrConnection->CursorLocation = adUseServer;
или adUseClient посмотри гда меньше жрать будет
...
Рейтинг: 0 / 0
01.12.2003, 13:01
    #32339298
Ой Вэй
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Проблемы с памятью при работе с базой данных
Возможно это слегка не в тему, но правильнее объединять таблицы JOIN'ом, а не WHERE:
SELECT DocNum, Name FROM Clients AS Cl INNER JOIN DocHeads AS DH ON DH.ClientID = Cl.ExternalID

Более того, лучше написать
DocHeads AS DH INNER JOIN Clients AS Cl ON Cl.ExternalID = DH.ClientID,
т.е. начать с маленькой таблицы.

Не исключено, что тогда и SQL Server догадается, что нужна не вся таблица Clients.

Clients.ExternalID, DocHeads.ClientID -- уникальные индексы?
...
Рейтинг: 0 / 0
01.12.2003, 14:10
    #32339421
_Konst
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Проблемы с памятью при работе с базой данных
Хорошо бы увидеть код после Execute...
Может в цикле не вызывается ReleaseRows???
Какой используется аксессор? Кто в нем владеет памятью?
...
Рейтинг: 0 / 0
01.12.2003, 16:22
    #32339674
grifon
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Проблемы с памятью при работе с базой данных
Ой Вэй писал:Возможно это слегка не в тему, но правильнее объединять таблицы JOIN'ом, а не WHERE

Спасибо за совет.

_Konst писал:Хорошо бы увидеть код после Execute...

Решил привести код по открытию БД ( OpenDatabase ) и при выполнении запроса GetAllStocks(HWND g_hDlg)
HRESULT Mains::OpenDatabase()
{
HRESULT hr = NOERROR;
DBPROP dbprop[1];
DBPROPSET dbpropset[1];
IDBInitialize *pIDBInitialize = NULL;
IDBProperties *pIDBProperties = NULL;

VariantInit(&dbprop[0].vValue);

hr = CoCreateInstance( CLSID_SQLSERVERCE_2_0, 0, CLSCTX_INPROC_SERVER, IID_IDBInitialize, (void**)&pIDBInitialize);
if(FAILED(hr))
{
goto Exit;
}

dbprop[0].dwPropertyID = DBPROP_INIT_DATASOURCE;
dbprop[0].dwOptions = DBPROPOPTIONS_REQUIRED;
dbprop[0].vValue.vt = VT_BSTR;
dbprop[0].vValue.bstrVal= SysAllocString(DATABASE_PRESALE);
if(NULL == dbprop[0].vValue.bstrVal)
{
hr = E_OUTOFMEMORY;
goto Exit;
}

dbpropset[0].guidPropertySet = DBPROPSET_DBINIT;
dbpropset[0].rgProperties = dbprop;
dbpropset[0].cProperties = sizeof(dbprop)/sizeof(dbprop[0]);
hr = pIDBInitialize->QueryInterface(IID_IDBProperties, (void **)&pIDBProperties);
if(FAILED(hr))
{
goto Exit;
}

hr = pIDBProperties->SetProperties(1, dbpropset);
if(FAILED(hr))
{
goto Exit;
}

hr = pIDBInitialize->Initialize();
if(FAILED(hr))
{
goto Exit;
}

hr = pIDBInitialize->QueryInterface(IID_IDBCreateSession, (void**)&m_pIDBCreateSession);

Exit:
VariantClear(&dbprop[0].vValue);

if(pIDBProperties)
{
pIDBProperties->Release();
}

if (pIDBInitialize)
{
pIDBInitialize->Release();
}

return hr;
}

HRESULT Mains::GetAllStocks(HWND g_hDlg)
{
HRESULT hr = NOERROR;
DBBINDING *pDBBindings;
DBBINDSTATUS *pDBBindStatus = NULL;
ULONG cbRow = 0;
IDBCreateCommand*pIDBCreateCommand = NULL;
ICommandText *pICommandText = NULL;
IAccessor *pIAccessor = NULL;
IOpenRowset *pIOpenRowset = NULL;
IRowset *pIRowset = NULL;
HACCESSOR hAccessor = DB_NULL_HACCESSOR;
IColumnsInfo *pIColumnsInfo;
ULONG nCols;
DBCOLUMNINFO *pColumnsInfo = NULL;
OLECHAR *pColumnStrings = NULL;

ULONG cRowsObtained;
HROW rghRows[1];
HROW * pRows = rghRows;
char * pRowValues;
LPWSTR sqlQuery = NULL;
WCHAR *pwszName = NULL;
LVITEM lvTest;
UINT iIndex = 0;
HWND hListViewCtrl;
ULONG nCol;

if (NULL == m_pIDBCreateSession)
{
hr = E_POINTER;
goto Exit;
}

hr = m_pIDBCreateSession->CreateSession(NULL, IID_IDBCreateCommand, (IUnknown**) &pIDBCreateCommand);
if (FAILED(hr))
{
goto Exit;
}

hr = pIDBCreateCommand->CreateCommand(NULL, IID_ICommandText, (IUnknown**) &pICommandText);
if (FAILED(hr))
{
goto Exit;
}

sqlQuery = (LPWSTR)CoTaskMemAlloc(200);
wsprintf(sqlQuery, L"SELECT DocNum, Name FROM DocHeads AS DH INNER JOIN Clients AS Cl ON Cl.ExternalID = DH.ClientID");

hr = pICommandText->SetCommandText(DBGUID_DBSQL, sqlQuery);
if (FAILED(hr))
{
goto Exit;
}

hr = pICommandText->Execute(NULL, IID_IRowset, NULL, NULL, (IUnknown**) &pIRowset);
if(FAILED(hr))
{
goto Exit;
}

hr=pIRowset->QueryInterface(IID_IColumnsInfo, (void**)&pIColumnsInfo);
if (FAILED(hr))
{
goto Exit;
}

hr = pIColumnsInfo->GetColumnInfo(&nCols, &pColumnsInfo,&pColumnStrings);
if (FAILED(hr))
{
goto Exit;
}

pDBBindings = new DBBINDING[nCols];

for (nCol = 0; nCol < nCols; nCol++)
{
pDBBindings[nCol].iOrdinal = nCol+1;
pDBBindings[nCol].obValue = cbRow;
pDBBindings[nCol].obLength = 0;
pDBBindings[nCol].obStatus = 0;
pDBBindings[nCol].pTypeInfo = NULL;
pDBBindings[nCol].pObject = NULL;
pDBBindings[nCol].pBindExt = NULL;
pDBBindings[nCol].dwPart = DBPART_VALUE;
pDBBindings[nCol].dwMemOwner = DBMEMOWNER_CLIENTOWNED;
pDBBindings[nCol].eParamIO = DBPARAMIO_NOTPARAM;
pDBBindings[nCol].cbMaxLen = 2*(pColumnsInfo[nCol].ulColumnSize + 1);
pDBBindings[nCol].dwFlags = 0;
pDBBindings[nCol].wType = pColumnsInfo[nCol].wType;
pDBBindings[nCol].bPrecision = pColumnsInfo[nCol].bPrecision;
pDBBindings[nCol].bScale = pColumnsInfo[nCol].bScale;
cbRow += pDBBindings[nCol].cbMaxLen;
}

pDBBindStatus = new DBBINDSTATUS[nCols];

hr=pIRowset->QueryInterface(IID_IAccessor, (void**) &pIAccessor);
if (FAILED(hr))
{
goto Exit;
}

hr = pIAccessor->CreateAccessor(DBACCESSOR_ROWDATA,nCols, pDBBindings,0,&hAccessor,pDBBindStatus);
if (FAILED(hr))
{
goto Exit;
}

pRowValues = new char[cbRow];

hListViewCtrl = GetDlgItem(g_hDlg, IDC_STOCKSLIST);
ListView_DeleteAllItems(hListViewCtrl);
pwszName = (WCHAR*)CoTaskMemAlloc(pDBBindings[0].cbMaxLen + pDBBindings[1].cbMaxLen + 2);

CurrentStockID = 1;
hr = pIRowset->GetNextRows(DB_NULL_HCHAPTER,0,1,&cRowsObtained,&pRows );
while (SUCCEEDED(hr) && DB_S_ENDOFROWSET != hr)
{
pIRowset->GetData(pRows[0], hAccessor, pRowValues);

wsprintf(pwszName, L"%d", *(int*)(pRowValues+pDBBindings[0].obValue));

lvTest.mask = LVIF_TEXT | LVIF_STATE;
lvTest.iItem = 0;
lvTest.pszText = pwszName;
lvTest.iIndent = 0;
lvTest.stateMask = 0;
lvTest.state = 0;
lvTest.iSubItem = 0;

iIndex = ListView_InsertItem(hListViewCtrl, &lvTest);

wcscpy(pwszName, (WCHAR*)(pRowValues+pDBBindings[1].obValue));

ListView_SetItemText( hListViewCtrl,iIndex,2,pwszName);
CurrentStockID++;

hr = pIRowset->ReleaseRows(1, pRows, NULL, NULL, NULL);
if(FAILED(hr))
{
goto Exit;
}
hr = pIRowset->GetNextRows(DB_NULL_HCHAPTER, 0, 1, &cRowsObtained, &pRows);
}

Exit:
if (pRows)
{
CoTaskMemFree(pRows);
pRows = NULL;
}

if (pwszName)
{
CoTaskMemFree(pwszName);
pwszName = NULL;
}

if (sqlQuery)
{
CoTaskMemFree(sqlQuery);
sqlQuery = NULL;
}

if(pDBBindings)
{
delete [] pDBBindings;
}

if(pDBBindStatus)
{
delete [] pDBBindStatus;
}

if(pIAccessor)
{
pIAccessor->ReleaseAccessor(hAccessor, NULL);
pIAccessor->Release();
}

if(pRowValues)
{
delete [] pRowValues;
}

if(pIColumnsInfo)
{
pIColumnsInfo->Release();
}

if(pIRowset)
{
pIRowset->Release();
}

if(pICommandText)
{
pICommandText->Release();
}

if(pIDBCreateCommand)
{
pIDBCreateCommand->Release();
}

return hr;
}
...
Рейтинг: 0 / 0
01.12.2003, 16:49
    #32339727
grifon
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Проблемы с памятью при работе с базой данных
Меня сейчас больше волнует проблема при использовании позиционирования в таблице. Суть проблемы: есть ListView, в котором отображается набор записей, полученных с помощью запроса. В ListView выбирается строка, а в соответствующих Edit'ах должна отображаться информация из полей таблицы. Для этого делаю Seek. Но постоянно вылетает: "First-chance exception in presale.exe: 0xC0000005: Access Violation" . и в режиме отладки прога вылетает в ассемблерный код. Ошибка появляется чаще всего после нескольких вызовов функции, в которой и осуществляется позиционирование.

Попытаюсь привести код функции, в которой происходит ошибка:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
HRESULT Goods::FindGoodInObjects(int *NewGoodFlag, LPWSTR Articul)
{
	HRESULT		hr			= NOERROR;			
	DBBINDING	*prgBinding		= NULL;			
	HROW		rghRows[ 1 ];						
	HROW		*prghRows		= rghRows;		
   	ULONG		cRowsObtained		=  0 ;				
	BYTE		*pData			= NULL;			
	DWORD		dwBindingSize		=  0 ;
	DWORD		dwIndex			=  0 ;
	DWORD		dwOffset		=  0 ;
	IRowset		*pIRowset		= NULL;			
	IRowsetIndex	*pIRowsetIndex		= NULL;				
	IAccessor	*pIAccessor		= NULL;		
	HACCESSOR	hAccessor		= DB_NULL_HACCESSOR;
	WCHAR*		pwszDocObj[]		=	{
								L "Articul" 
							};

	dwBindingSize = sizeof(pwszDocObj)/sizeof(pwszDocObj[ 0 ]);
	prgBinding = (DBBINDING*)CoTaskMemAlloc(sizeof(DBBINDING)*dwBindingSize);
	if (NULL == prgBinding)
	{
		hr = E_OUTOFMEMORY;
		goto Exit;
	}

	hr = g_pODBInterf->GetFieldsOfSeek(m_pIDBCreateSession, L "DocObj" , L "PK_DOCNUM_ARTICUL" , &pIRowset, &pIRowsetIndex, prgBinding, &dwOffset, pwszDocObj, dwBindingSize);
	if(FAILED(hr))
	{
		goto Exit;
	}

	hr = pIRowset->QueryInterface(IID_IAccessor, (void**)&pIAccessor);
	if(FAILED(hr))
	{
		goto Exit;
	}

    	hr = pIAccessor->CreateAccessor(DBACCESSOR_ROWDATA, dwBindingSize, prgBinding,  0 , &hAccessor,NULL);
	if(FAILED(hr))
	{
     	   goto Exit;
	}

	pData = (BYTE*)CoTaskMemAlloc(dwOffset);
	if (NULL == pData)
	{
		hr = E_OUTOFMEMORY;
		goto Exit;
	}

    	memset(pData,  0 , dwOffset);

	*(DBSTATUS*)(pData+prgBinding[ 0 ].obStatus)	= DBSTATUS_S_OK;
	wcscpy((WCHAR*)(pData+prgBinding[ 0 ].obValue), Articul);
	*(ULONG*)(pData+prgBinding[ 0 ].obLength)	= wcslen((WCHAR*)(pData+prgBinding[ 0 ].obValue))*sizeof(WCHAR);

	hr = pIRowsetIndex->Seek(hAccessor,  1 , pData, DBSEEK_FIRSTEQ);
	if(FAILED(hr))
	{
		goto Exit;	
	}

	hr = pIRowset->GetNextRows(DB_NULL_HCHAPTER,  0 ,  1 , &cRowsObtained, &prghRows);
	if(FAILED(hr))
	{
		goto Exit;	
	}

	if (DB_S_ENDOFROWSET != hr)
	{
		hr = pIRowset->GetData(prghRows[ 0 ], hAccessor, pData);
		if (FAILED(hr))
		{
			goto Exit;
		}

		*NewGoodFlag =  1 ;
	}

	pIRowset->ReleaseRows( 1 , prghRows, NULL, NULL, NULL);

Exit:
	if (prghRows)
	{
        CoTaskMemFree(prghRows);
        prghRows = NULL;
	}

	if (prgBinding)
	{
        	CoTaskMemFree(prgBinding);
	        prgBinding = NULL;
	}

	if (pData)
	{
	        CoTaskMemFree(pData);
		pData = NULL;
	}

	if(pIAccessor)
	{
		pIAccessor->ReleaseAccessor(hAccessor, NULL); 
		pIAccessor->Release();
		pIAccessor = NULL;
	}

	if(pIRowset)
	{
		pIRowset->Release();
		pIRowset = NULL;
	}

	if (pIRowsetIndex)
	{
		pIRowsetIndex->Release();
		pIRowsetIndex = NULL;
	}

	return hr;
}


Насколько я смог определить, ошибка происходит в последнем Release, т.е. при попытке выполнить: pIRowsetIndex->Release();
По крайней мере при пошаговом выполнении при попытке выполнить его, вылетает Access Violation

Из FindGoodInObjects вызывается следующая функция:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
HRESULT ODBInterf::GetFieldsOfSeek(IDBCreateSession *m_pIDBCreateSession, WCHAR *TableName, WCHAR* IndexName, IRowset **ppIRowset, IRowsetIndex **ppIRowsetIndex, DBBINDING *prgBinding, DWORD *dwOffset, WCHAR** NameRecords, DWORD dwBindingSize)
{
	HRESULT		hr		= NOERROR;	
	HROW		rghRows[ 1 ];	
	HROW		*prghRows	= rghRows;
	DBID		TableID;								
	DBID		IndexID;								
	DBPROPSET	rowsetpropset[ 1 ];
	DBPROP		rowsetprop[ 1 ];	
   	ULONG		cRowsObtained	=  0 ;				
	DBOBJECT	dbObject;
	DBCOLUMNINFO	*pDBColumnInfo	= NULL;				
	WCHAR		*pStringsBuffer	= NULL;
	DWORD		dwIndex		=  0 ;
	DWORD		dwOrdinal	=  0 ;
	ULONG		ulNumCols;

	IOpenRowset	*pIOpenRowset	= NULL;				
	IRowset		*pIRowset	= NULL;			
	IRowsetIndex	*pIRowsetIndex	= NULL;				
	ILockBytes	*pILockBytes	= NULL;			
	IColumnsInfo	*pIColumnsInfo	= NULL;				

	VariantInit(&rowsetprop[ 0 ].vValue);

	if (NULL == m_pIDBCreateSession)
	{
		hr = E_POINTER;
		goto Exit;
	}

	hr = m_pIDBCreateSession->CreateSession(NULL, IID_IOpenRowset, (IUnknown**) &pIOpenRowset);
	if(FAILED(hr))
	{
        	goto Exit;
	}

	TableID.eKind	= DBKIND_NAME;
	TableID.uName.pwszName	= TableName;

	IndexID.eKind	= DBKIND_NAME;
	IndexID.uName.pwszName	= IndexName;

	rowsetpropset[ 0 ].cProperties	=  1 ;
	rowsetpropset[ 0 ].guidPropertySet= DBPROPSET_ROWSET;
	rowsetpropset[ 0 ].rgProperties	= rowsetprop;

	rowsetprop[ 0 ].dwPropertyID	= DBPROP_IRowsetIndex;
	rowsetprop[ 0 ].dwOptions		= DBPROPOPTIONS_REQUIRED;
	rowsetprop[ 0 ].colid		= DB_NULLID;
	rowsetprop[ 0 ].vValue.vt		= VT_BOOL;
	rowsetprop[ 0 ].vValue.boolVal	= VARIANT_TRUE;

	hr = pIOpenRowset->OpenRowset(	NULL, &TableID,	&IndexID,IID_IRowsetIndex,				sizeof(rowsetpropset)/sizeof(rowsetpropset[ 0 ]),	rowsetpropset, (IUnknown**) &pIRowsetIndex);
	if(FAILED(hr))
	{
		goto Exit;
	}

	if(pIOpenRowset)
	{
		pIOpenRowset->Release();
		pIOpenRowset = NULL;
	}

	VariantClear(&rowsetprop[ 0 ].vValue);

	hr = pIRowsetIndex->QueryInterface(IID_IRowset, (void**) &pIRowset);
	if(FAILED(hr))
	{
		goto Exit;
	}

	hr = pIRowset->QueryInterface(IID_IColumnsInfo, (void **)&pIColumnsInfo);
	if(FAILED(hr))
	{
		goto Exit;
	}

	hr = pIColumnsInfo->GetColumnInfo(&ulNumCols, &pDBColumnInfo, &pStringsBuffer);
	if(FAILED(hr) ||  0  == ulNumCols)
	{
		goto Exit;
	}

	*dwOffset =  0 ;

	for (dwIndex =  0 ; dwIndex < dwBindingSize; ++dwIndex)
   	{
		if (!GetColumnOrdinal(pDBColumnInfo, ulNumCols, NameRecords[dwIndex], &dwOrdinal))
		{
			hr = E_FAIL;
			goto Exit;
		}

		prgBinding[dwIndex].iOrdinal	= dwOrdinal;
		prgBinding[dwIndex].dwPart		= DBPART_VALUE | DBPART_STATUS | DBPART_LENGTH;
		prgBinding[dwIndex].obLength	= *dwOffset;                                     
		prgBinding[dwIndex].obStatus	= prgBinding[dwIndex].obLength + sizeof(ULONG);  
		prgBinding[dwIndex].obValue		= prgBinding[dwIndex].obStatus + sizeof(DBSTATUS);
		prgBinding[dwIndex].pTypeInfo	= NULL;
		prgBinding[dwIndex].pBindExt	= NULL;
		prgBinding[dwIndex].dwMemOwner	= DBMEMOWNER_CLIENTOWNED;
		prgBinding[dwIndex].dwFlags		=  0 ;
		prgBinding[dwIndex].bPrecision	= pDBColumnInfo[dwOrdinal].bPrecision;
		prgBinding[dwIndex].bScale		= pDBColumnInfo[dwOrdinal].bScale;

		switch(pDBColumnInfo[dwOrdinal].wType)
		{
		case DBTYPE_BYTES:
			dbObject.dwFlags = STGM_READ;
			dbObject.iid	 = IID_ILockBytes;

			prgBinding[dwIndex].pObject		= &dbObject;
			prgBinding[dwIndex].cbMaxLen	= sizeof(IUnknown*);
			prgBinding[dwIndex].wType		= DBTYPE_IUNKNOWN;
			break;

		case DBTYPE_WSTR:
			prgBinding[dwIndex].pObject		= NULL;
			prgBinding[dwIndex].wType		= pDBColumnInfo[dwOrdinal].wType;
			prgBinding[dwIndex].cbMaxLen	= sizeof(WCHAR)*(pDBColumnInfo[dwOrdinal].ulColumnSize +  1 );
			break;

		default:
			prgBinding[dwIndex].pObject		= NULL;
			prgBinding[dwIndex].wType		= pDBColumnInfo[dwOrdinal].wType;
			prgBinding[dwIndex].cbMaxLen	= pDBColumnInfo[dwOrdinal].ulColumnSize; 
			break;
		}

		*dwOffset = prgBinding[dwIndex].obValue + prgBinding[dwIndex].cbMaxLen;

		*dwOffset = ROUND_UP(*dwOffset, COLUMN_ALIGNVAL);
	}

	*ppIRowset = pIRowset;
	*ppIRowsetIndex = pIRowsetIndex;

Exit:
	if (pIColumnsInfo)
	{
		pIColumnsInfo->Release();
		pIColumnsInfo = NULL;
	}

	if (pStringsBuffer)
	{
        	CoTaskMemFree(pStringsBuffer);
	        pStringsBuffer = NULL;
    	}

	if (pDBColumnInfo)
	{
        	CoTaskMemFree(pDBColumnInfo);
	        pDBColumnInfo = NULL;
	}

	return hr;
}
...
Рейтинг: 0 / 0
01.12.2003, 17:49
    #32339830
_Konst
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Проблемы с памятью при работе с базой данных
По поводу Access Violation, если глаза вас не обманули и программа действительно падает на Release, все объясняется очень просто - этот Release лишний - предыдущий вызов Release убил объект и все его интерфейсы указывают далее в никуда.
Про отъедание памяти ничего не скажу - не нашел :(, хотя это не значит, что этого не происходит. Чего бы вам не воспользоваться NuMega Bounds Checker-ом? Ну или не вставить все это в обычный Visual с директивой
Код: plaintext
1.
2.
3.
4.
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

он и покажет, если чего не освобождаете.
...
Рейтинг: 0 / 0
02.12.2003, 00:49
    #32340047
grifon
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Проблемы с памятью при работе с базой данных
_Konst писал:По поводу Access Violation, если глаза вас не обманули и программа действительно падает на Release, все объясняется очень просто - этот Release лишний - предыдущий вызов Release убил объект и все его интерфейсы указывают далее в никуда.

Все дело в том, что Access Violation вылетает не каждый раз :(
Функция может отработать 10-15-20 раз и все будет нормально, а может рухнуть после первой же попытке...
...
Рейтинг: 0 / 0
02.12.2003, 15:46
    #32340917
_Konst
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Проблемы с памятью при работе с базой данных
А это ни о чем не говорит. Стандарт OLE не обязывает кокласс удалять себя немедленно по достижении счетчиком сылок нуля. В некоторых случаях бывает даже полезно заблокировать кокласс в памяти (фабрике классов для этого сделали ф-ию LockServer). Попробуйте перед последним Release-ом вызвать ф-ию CoFreeUnusedLibraries - возможно это "стабилизирует" ситуацию
...
Рейтинг: 0 / 0
03.12.2003, 15:29
    #32342199
grifon
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Проблемы с памятью при работе с базой данных
Спасибо за ваши советы... Но, к сожалению ничего так и не помогло...

По поводу Access Violation:
после долгих мучений смог откопать такую вещь: после того как закоментировал строки с использованием динамических переменных ошибок больше не наблюдалось. На мой взгляд использование верное, поэтому прошу вашей помощи. То, что закоментировано, указано дополнительно. После закоментированных строк написаны аналоги, только без применения динамических переменных. Помогите разобраться, не могу понять в чем дело.
Судя по всему, работа с базой здесь совсем не причем...

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
212.
213.
214.
215.
216.
217.
218.
219.
220.
221.
222.
223.
224.
225.
226.
227.
228.
229.
230.
231.
232.
233.
234.
HRESULT Goods::GoodsListChange(HWND g_hDlg)
{
	HRESULT				hr					= NOERROR;			// Error code reporting
	DBBINDING			*prgBinding			= NULL;				// Binding used to create accessor
	HROW				rghRows[ 1 ];								// Array of row handles obtained from the rowset object
	HROW				*prghRows			= rghRows;			// Row handle(s) pointer
   	ULONG				cRowsObtained		=  0 ;				// Number of rows obtained from the rowset object
	BYTE				*pData				= NULL;				// record data
	DWORD				dwBindingSize		=  0 ;
	DWORD				dwIndex				=  0 ;
	DWORD				dwOffset			=  0 ;

	IRowset				*pIRowset			= NULL;				// Provider Interface Pointer
	IRowsetIndex		*pIRowsetIndex		= NULL;				// Provider Interface Pointer
	IAccessor			*pIAccessor			= NULL;				// Provider Interface Pointer
	HACCESSOR			hAccessor			= DB_NULL_HACCESSOR;// Accessor handle
//	HWND				hObject;
	LPWSTR				Articul				= NULL;
	IOpenRowset			*pIOpenRowset		= NULL;				// Provider Interface Pointer
	LPWSTR				pwszName			= NULL;

	WCHAR*				pwszGoods[]		=	{						// Employee info Column names
													L "Articul" ,
													L "Name" ,
													L "InPlace" ,
													L "Price" 
												};

Это было закоментировано намеренно:
 /*
	hObject = GetDlgItem(g_hDlg, IDC_GOODSLIST);
	dwIndex = ListView_GetSelectionMark(hObject);

	Articul = (LPWSTR)CoTaskMemAlloc(7);
	ListView_GetItemText(hObject, dwIndex, 0, Articul, 7);
*/ 
	pwszName = (LPWSTR)CoTaskMemAlloc( 10 );

	dwBindingSize = sizeof(pwszGoods)/sizeof(pwszGoods[ 0 ]);
	prgBinding = (DBBINDING*)CoTaskMemAlloc(sizeof(DBBINDING)*dwBindingSize);
	if (NULL == prgBinding)
	{
		hr = E_OUTOFMEMORY;
		goto Exit;
	}

	hr = g_pODBInterf->GetFieldsOfSeek(m_pIDBCreateSession, L "Goods" , L "PK_ARTICUL" , &pIOpenRowset, &pIRowset, &pIRowsetIndex, prgBinding, &dwOffset, pwszGoods, dwBindingSize);
	if(FAILED(hr))
	{
		goto Exit;
	}

	// Get IAccessor interface
	//
	hr = pIRowset->QueryInterface(IID_IAccessor, (void**)&pIAccessor);
	if(FAILED(hr))
	{
		goto Exit;
	}

    // Create accessor.
	//
    hr = pIAccessor->CreateAccessor(DBACCESSOR_ROWDATA, 
									dwBindingSize, 
									prgBinding,
									 0 ,
									&hAccessor,
									NULL);
    if(FAILED(hr))
    {
        goto Exit;
    }

	// Allocate data buffer for seek and retrieve operation.
	//
	pData = (BYTE*)CoTaskMemAlloc(dwOffset);
	if (NULL == pData)
	{
		hr = E_OUTOFMEMORY;
		goto Exit;
	}

    // Set data buffer to zero
    //
    memset(pData,  0 , dwOffset);

    // Set data buffer for seek operation
    //
	*(DBSTATUS*)(pData+prgBinding[ 0 ].obStatus)	= DBSTATUS_S_OK;

Вместо этой строки вставлена следующая, которая вместо Articul использует постоянное значение
//	wcscpy((WCHAR*)(pData+prgBinding[ 0 ].obValue), Articul);
	wcscpy((WCHAR*)(pData+prgBinding[ 0 ].obValue), L "13865 ");

	*(ULONG*)(pData+prgBinding[ 0 ].obLength)		= wcslen((WCHAR*)(pData+prgBinding[ 0 ].obValue))*sizeof(WCHAR);

 	// Position at a key value within the current range 
	//
	hr = pIRowsetIndex->Seek(hAccessor,  1 , pData, DBSEEK_FIRSTEQ);
	if(FAILED(hr))
	{
		goto Exit;	
	}

    // Retrieve a row handle for the row resulting from the seek
    //
    hr = pIRowset->GetNextRows(DB_NULL_HCHAPTER,  0 ,  1 , &cRowsObtained, &prghRows);
	if (DB_S_ENDOFROWSET != hr)
	{
		// Fetch actual data
		//
		hr = pIRowset->GetData(prghRows[ 0 ], hAccessor, pData);
		if (FAILED(hr))
		{
			pIRowset->ReleaseRows( 1 , prghRows, NULL, NULL, NULL);
			goto Exit;
		}

		// Update dialog
		// If return a null value or status is not OK, ignore the contents of the value and length parts of the buffer.
		//
		if (DBSTATUS_S_ISNULL != *(DBSTATUS *)(pData+prgBinding[ 1 ].obStatus) &&
            DBSTATUS_S_OK == *(DBSTATUS *)(pData+prgBinding[ 1 ].obStatus))
		{
			SetDlgItemText(g_hDlg, IDC_GOOD, (WCHAR*)(pData+prgBinding[ 1 ].obValue));
		} 

		if (DBSTATUS_S_ISNULL != *(DBSTATUS *)(pData+prgBinding[ 2 ].obStatus) &&
            DBSTATUS_S_OK == *(DBSTATUS *)(pData+prgBinding[ 2 ].obStatus))
		{

Эти строки также заменены на строку без испоьзования динамически содаваемой переменной:
//			wsprintf(pwszName, L "%d" , *(int*)(pData+prgBinding[ 2 ].obValue));
//			SetDlgItemText(g_hDlg, IDC_INPLACEVALUE, pwszName);
						SetDlgItemText(g_hDlg, IDC_INPLACEVALUE, L "0 . 0 ");
		}

		if (DBSTATUS_S_ISNULL != *(DBSTATUS *)(pData+prgBinding[ 3 ].obStatus) &&
            DBSTATUS_S_OK == *(DBSTATUS *)(pData+prgBinding[ 3 ].obStatus))
		{

Эти строки также заменены на строку без испоьзования динамически содаваемой переменной:
//			wsprintf(pwszName, L "%f" , *(float*)(pData+prgBinding[ 3 ].obValue));
//			SetDlgItemText(g_hDlg, IDC_PRICEVALUE, pwszName);
			SetDlgItemText(g_hDlg, IDC_PRICEVALUE, L "0 . 00 ");
		}

		hr = pIRowset->ReleaseRows( 1 , prghRows, NULL, NULL, NULL);
        if(FAILED(hr))
        {
			goto Exit;
        }
	}

Exit:

	if (prghRows)
	{
        CoTaskMemFree(prghRows);
        prghRows = NULL;
	}

	if(pIAccessor)
	{
		hr = pIAccessor->ReleaseAccessor(hAccessor, NULL); 
		if (FAILED(hr))
		{
			MessageBox(g_hDlg, L "Error" , L "Goods" , MB_OK);
		}
		hr = pIAccessor->Release();
		if (FAILED(hr))
		{
			MessageBox(g_hDlg, L "Error" , L "Goods" , MB_OK);
		}
		pIAccessor = NULL;
	}

	if (pData)
	{
        CoTaskMemFree(pData);
		pData = NULL;
	}

	if(pIRowset)
	{
		hr = pIRowset->Release();
		if (FAILED(hr))
		{
			MessageBox(g_hDlg, L "Error" , L "Goods" , MB_OK);
		}

		pIRowset = NULL;
	}

	if (pIRowsetIndex)
	{
		hr = pIRowsetIndex->Release();
		if (FAILED(hr))
		{
			MessageBox(g_hDlg, L "Error" , L "Goods" , MB_OK);
		}

		pIRowsetIndex = NULL;
	}
    
	if (pIOpenRowset)
	{
		hr = pIOpenRowset->Release();
		if (FAILED(hr))
		{
			MessageBox(g_hDlg, L "Error" , L "Goods" , MB_OK);
		}
		pIOpenRowset = NULL;
	}
	
	if (prgBinding)
    {
        CoTaskMemFree(prgBinding);
        prgBinding = NULL;
    }

	if (pwszName)
	{
		CoTaskMemFree(pwszName);
		pwszName = NULL;
	}

	if (Articul)
	{
		CoTaskMemFree(Articul);
		Articul = NULL;
	}

	return hr;
}
...
Рейтинг: 0 / 0
03.12.2003, 18:41
    #32342503
_Konst
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Проблемы с памятью при работе с базой данных
Пока нет времени детально вникнуть в ваш код.
Но одно можно сказать точно - правильное динамическое выделение памяти (если оно правильное) здесь ни при чем. Я это утверждаю не потому, что просто верю SQL Server-у. Сам пользуюсь классом (своим же) для чтения произвольной таблицы произвольного провайдера (в частности SQL Server) в текстовом виде. Понятно, что биндинги у меня динамические, правда, память под даннные я выделяю по new, а не CoTaskMemAlloc-ом. Все работает! Мне правда, почему-то не удается открыть индекс... а очень хочется, приходится по тупому позиционироваться на запись.
А под эти КПК нельзя использовать ATL? Там все, что вам нужно займет от силы строчек 20...
...
Рейтинг: 0 / 0
03.12.2003, 21:36
    #32342676
grifon
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Проблемы с памятью при работе с базой данных
Спасибо за помощь и поддержку. Решение оказалось как всегда на поверхности. Похоже я памяти мало выделял под переменные. Выделил побольше и все заработало. Ух.

Спасибо огромное за помощь.
...
Рейтинг: 0 / 0
03.12.2003, 22:12
    #32342688
grifon
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Проблемы с памятью при работе с базой данных
_KonstА под эти КПК нельзя использовать ATL? Там все, что вам нужно займет от силы строчек 20...

Похоже что есть, но уже поздно пить боржоми :) Надо было раньше думать. Тут до конца проекта осталось не так много...
Ещё раз спасибо.
...
Рейтинг: 0 / 0
Форумы / C++ [игнор отключен] [закрыт для гостей] / Проблемы с памятью при работе с базой данных / 15 сообщений из 15, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]