2017-02-20 15 views
1

Вот фрагмент расширения для TCL, написанный на C (++) (что здесь C++ не имеет значения - я просто использую std::vector). Я использую Tcl_Format для создания новой форматированной строки. Если я не использую Tcl_DecrRefCount, сообщает Xcode больше и больше памяти используется каждый раз, когда эта внешняя процедура называется:Использование памяти Tcl_Format

int TclME::vTestExt(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj* const objv[]) 
{ 
    Tcl_Obj *resultPtr, *item[1], *itemFormatted; 
    size_t N; 
    std::vector<long> v; 
    populate_v(v); 
    N = v.size(); 
    resultPtr = Tcl_NewListObj(0, NULL); 
    for (long i = 0; i < N; ++i) { 
     item[0] = Tcl_NewLongObj(v[i]); 
     printf("item[0] ref %i, sh %i; ", item[0]->refCount, Tcl_IsShared(item[0])); 
     itemFormatted = Tcl_Format(interp, "#%06X", 1, item); 
     // With Tcl_DecrRefCount commented out, there is a memory leak 
     printf("\tref %i, sh %i; ", item[0]->refCount, Tcl_IsShared(item[0])); 
     Tcl_DecrRefCount(item[0]); 
     printf("\tref %i, sh %i\n", item[0]->refCount, Tcl_IsShared(item[0])); 

     Tcl_ListObjAppendElement(interp, resultPtr, itemFormatted); 
    } 
    Tcl_SetObjResult(interp, resultPtr); 
    return TCL_OK; 
} 

void populate_v(std::vector<long> &v) устанавливает вектор элементов.

Выход item[0] ref 0, sh 0; ref 0, sh 0; ref -1, sh 0, поэтому я не ожидал, что вам придется позвонить Tcl_DecrRefCount вручную.

Что я пропустил?

ответ

3

При создании нового объекта TCL, его счетчик ссылок 0.

Любой объект TCL является предметом освобождаться когда счетчик ссылок капель на 0. Таким образом, чистый путь будет сначала приращение контрольный счетчик после создания объекта, а затем декремент он снова, когда он больше не используется (после звонка на Tcl_Format() например).

В вашем частном случае выше, вы можете обойти эту проблему с помощью Tcl_ObjPrintf():

... 
for (long i = 0; i < N; ++i) { 
    Tcl_ListObjAppendElement(interp, resultPtr, Tcl_ObjPrintf("#%06X", v[i])); 
} 
... 
+0

желание, которое я мог бы дать 2+, для 'Tcl_ObjPrintf' и объясняя * капля * немного. – zeeMonkeez

+0

Раньше это было очень неприятно, чтобы генерировать подобные вещи; поэтому добавлен Tcl_ObjPrintf'. –