这是用C(++)编写的TCL的扩展proc(它的C ++在这里没关系 - 我只使用fx.average <- function(df, varlist) {
df %>%
dplyr::select_(.dots = varlist) %>%
dplyr::group_by_(.dots = "var1") %>%
dplyr::summarise_each(funs(mean(., na.rm = TRUE)))
}
fx.average(mydf, varlist0)
# A tibble: 24 × 3
# var1 var2 var3
# <fctr> <dbl> <dbl>
#1 1 55.13601 1141.021
#2 2 59.16508 1155.226
#3 3 59.64524 1245.043
#4 4 60.12310 1284.808
#5 5 57.65874 1221.771
#6 6 58.86611 1266.026
#7 7 66.13987 1303.927
#8 8 54.21595 1303.638
#9 9 63.84230 1280.380
#10 10 49.15238 1236.456
# ... with 14 more rows
)。
我使用std::vector
创建一个新的格式化字符串。如果我不使用Tcl_Format
,Xcode会报告每次调用此外部过程时使用的内存越来越多:
Tcl_DecrRefCount
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
。
我错过了什么?
答案 0 :(得分:3)
创建新TCL对象时,其引用计数为0。
当引用计数器降为 0时,任何TCL对象都将被释放。因此,干净的方法是在创建对象后首先递增引用计数器然后在不再使用时再次递减(例如,在调用Tcl_Format()
之后)。
在上述特殊情况下,您可以使用Tcl_ObjPrintf()
:
...
for (long i = 0; i < N; ++i) {
Tcl_ListObjAppendElement(interp, resultPtr, Tcl_ObjPrintf("#%06X", v[i]));
}
...