Member 12677926 Ответов: 2

Allocsysstring в элементе управления деревом


Привет,

у меня вопрос относительно вставка элемента управления "дерево", как указано ниже:


m_cTreeCtrl.InsertItem(TVIF_TEXT | TVIF_IMAGE |
TVIF_SELECTEDIMAGE
| TVIF_PARAM, strTemp, 0, 0, 0, 0, (LPARAM)(LPCTSTR)(LPCTSTR)strParamval, m_hMatNode, TVI_LAST);

здесь вставляется strparamval

когда я получаю данные я не могу получить данные как указано ниже:

Элемент TVITEMEX;
item.mask = TVIF_PARAM;
пункт.hItem = hChildItem;
TreeView_GetItem(m_cTreeCtrl, &item);
CString strParam = (LPCTSTR)элемент.параметр lparam;


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

m_cTreeCtrl.InsertItem(TVIF_TEXT | TVIF_IMAGE |
TVIF_SELECTEDIMAGE| TVIF_PARAM, strTemp, 0, 0, 0, 0,
(LPARAM)strParamval.AllocSysString(),
m_hMatNode, TVI_LAST);


но так как эта логика является циклом, когда я выделяю и sysfreestring его дает неправильное значение в последний раз.

я сомневаюсь, что мы должны делать sysfreestring здесь, как это происходит в цикле for ?

Что я уже пробовал:

m_cTreeCtrl.InsertItem(TVIF_TEXT | TVIF_IMAGE |
TVIF_SELECTEDIMAGE| TVIF_PARAM, strTemp, 0, 0, 0, 0,
(LPARAM)strParamval.AllocSysString(),
m_hMatNode, TVI_LAST);

jeron1

Любая причина для 2 (LPCTSTR) ' s?

(LPARAM)(LPCTSTR)(LPCTSTR)strParamval

Richard MacCutchan

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

2 Ответов

Рейтинг:
1

Richard MacCutchan

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


Рейтинг:
0

Jochen Arndt

Это зависит от того, что вы хотите сохранить в элементе управления дерева. Если вы хотите задать текст элемента, используйте lpszItem параметр системы CTreeCtrl::InsertItem[^] метод. Это выделит память для хранения копии переданного текста и обработает освобождение при удалении элемента (или полного элемента управления деревом). Чтобы получить этот текст позже, используйте GetItemText метод, который возвращает a CString.

То lParam параметр предназначен для хранения дополнительной информации об элементе. Если это не укладывается в целое число, то это должен быть указатель на выделенную память (или фиксированную память, как строка const). С выделенной памятью вы несете ответственность за удаление при удалении элемента и удалении элемента управления дерева.

Если вы хотите например пройти а CString в качестве параметра, специфичного для конкретного приложения, выделите его с помощью new:

CString *pStrParam = new CString(strParamval);
m_cTreeCtrl.InsertItem(TVIF_TEXT | TVIF_IMAGE |
TVIF_SELECTEDIMAGE| TVIF_PARAM, strItemText, 0, 0, 0, 0,
    (LPARAM)pStrParam, m_hMatNode, TVI_LAST);
Чтобы удалить этот элемент позже:
TVITEMEX item;
item.mask = TVIF_PARAM;
item.hItem = hChildItem;
TreeView_GetItem(m_cTreeCtrl, &item);
CString *pStrParam = (CString*)item.lParam;
delete pStrParam;
Когда элемент управления удален, вышеизложенное должно быть сделано для каждого элемента.


Member 12677926

это дает ошибку

CString pStrParam = новый CString(strParamval);

Jochen Arndt

Уупс.
Извините, должно быть так
CString *pStrParam = new CString(strParamval);

Member 12677926

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

Jochen Arndt

Он не будет протекать, если вы удалите его.
Распространенным вариантом избежать утечек, как в вашем случае, является получение класса из CTreeView и добавление кода для удаления всей выделенной памяти в деструкторе. Класс также должен содержать другие функции, облегчающие обработку, например перезаписанную версию InsertItem (), которая выполняет выделение.

Member 12677926

actaully мы делаем новое в цикле for, так что он будет звонить много раз после этого мы удаляем, так что я думаю, что это будет утечка ?

Jochen Arndt

Утечка памяти означает, что часть выделенной памяти никогда не удаляется.
Если вы удалите его, он не будет протекать.

Использовали ли вы AllocSysString по определенной причине (передача OLE-данных в другое приложение / интерфейс)?

Member 12677926

я использовал allocsysstring и iam не передавая ole данные другому inerface

Jochen Arndt

Если вам не нужен BSTR, используйте вместо него новый. Он быстрее и использует кучу приложения, в то время как AllocSysString использует глобальную системную память.

Куча приложений будет освобождена при завершении работы приложения. Если есть утечки памяти, они не заботятся потом. Но с системной памятью они будут там до перезагрузки.