Skip to content

Commit 377c202

Browse files
More careful PROTECT()/UNPROTECT() in rbindlist for rchk (#6311)
* More careful PROTECT()/UNPROTECT() in rbindlist for rchk * use one UNPROTECT * initialize nprotect=2 * smaller diff
1 parent bcc0156 commit 377c202

File tree

2 files changed

+17
-14
lines changed

2 files changed

+17
-14
lines changed

inst/tests/tests.Rraw

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3046,8 +3046,8 @@ test(1006, print(as.data.table(M), nrows=10), output="gear NA.*1: 21.0")
30463046
# rbinding factor with non-factor/character
30473047
DT1 <- data.table(x=1:5, y=factor("a"))
30483048
DT2 <- data.table(x=1:5, y=2)
3049-
test(1007, rbindlist(list(DT1, DT2)), data.table(x = c(1:5, 1:5), y = factor(c(rep('a', 5), rep('2', 5)), levels = c('a', '2'))))
3050-
test(1008, rbindlist(list(DT2, DT1)), data.table(x = c(1:5, 1:5), y = factor(c(rep('2', 5), rep('a', 5)))))
3049+
test(1007.1, rbindlist(list(DT1, DT2)), data.table(x = c(1:5, 1:5), y = factor(c(rep('a', 5), rep('2', 5)), levels = c('a', '2'))))
3050+
test(1007.2, rbindlist(list(DT2, DT1)), data.table(x = c(1:5, 1:5), y = factor(c(rep('2', 5), rep('a', 5)))))
30513051

30523052
# rbindlist different types
30533053
DT1 <- data.table(a = 1L, b = 2L)

src/rbindlist.c

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -244,9 +244,9 @@ SEXP rbindlist(SEXP l, SEXP usenamesArg, SEXP fillArg, SEXP idcolArg, SEXP ignor
244244
ncol = length(VECTOR_ELT(l, first)); // ncol was increased as if fill=true, so reduce it back given fill=false (fill==false checked above)
245245
}
246246

247-
int nprotect = 0;
248-
SEXP ans = PROTECT(allocVector(VECSXP, idcol + ncol)); nprotect++;
249-
SEXP ansNames = PROTECT(allocVector(STRSXP, idcol + ncol)); nprotect++;
247+
int nprotect = 2;
248+
SEXP ans = PROTECT(allocVector(VECSXP, idcol + ncol));
249+
SEXP ansNames = PROTECT(allocVector(STRSXP, idcol + ncol));
250250
setAttrib(ans, R_NamesSymbol, ansNames);
251251
if (idcol) {
252252
SET_STRING_ELT(ansNames, 0, STRING_ELT(idcolArg, 0));
@@ -534,22 +534,25 @@ SEXP rbindlist(SEXP l, SEXP usenamesArg, SEXP fillArg, SEXP idcolArg, SEXP ignor
534534
if (w==-1 || !length(thisCol=VECTOR_ELT(li, w))) { // !length for zeroCol warning above; #1871
535535
writeNA(target, ansloc, thisnrow, false); // writeNA is integer64 aware and writes INT64_MIN
536536
} else {
537-
bool listprotect = false;
538-
if ((TYPEOF(target)==VECSXP || TYPEOF(target)==EXPRSXP) && TYPEOF(thisCol)!=TYPEOF(target)) {
539-
// do an as.list() on the atomic column; #3528
540-
thisCol = PROTECT(coerceVector(thisCol, TYPEOF(target))); listprotect = true;
537+
bool listprotect = (TYPEOF(target)==VECSXP || TYPEOF(target)==EXPRSXP) && TYPEOF(thisCol)!=TYPEOF(target);
538+
// do an as.list() on the atomic column; #3528
539+
if (listprotect) {
540+
thisCol = PROTECT(coerceVector(thisCol, TYPEOF(target)));
541+
// else coerces if needed within memrecycle; with a no-alloc direct coerce from 1.12.4 (PR #3909)
542+
const char *ret = memrecycle(target, R_NilValue, ansloc, thisnrow, thisCol, 0, -1, idcol+j+1, foundName);
543+
UNPROTECT(1); // earlier unprotect rbindlist calls with lots of lists #4536
544+
if (ret) warning(_("Column %d of item %d: %s"), w+1, i+1, ret);
545+
} else {
546+
const char *ret = memrecycle(target, R_NilValue, ansloc, thisnrow, thisCol, 0, -1, idcol+j+1, foundName);
547+
if (ret) warning(_("Column %d of item %d: %s"), w+1, i+1, ret);
541548
}
542-
// else coerces if needed within memrecycle; with a no-alloc direct coerce from 1.12.4 (PR #3909)
543-
const char *ret = memrecycle(target, R_NilValue, ansloc, thisnrow, thisCol, 0, -1, idcol+j+1, foundName);
544-
if (listprotect) UNPROTECT(1); // earlier unprotect rbindlist calls with lots of lists #4536
545-
if (ret) warning(_("Column %d of item %d: %s"), w+1, i+1, ret);
546549
// e.g. when precision is lost like assigning 3.4 to integer64; test 2007.2
547550
// TODO: but maxType should handle that and this should never warn
548551
}
549552
ansloc += thisnrow;
550553
}
551554
}
552555
}
553-
UNPROTECT(nprotect); // ans, coercedForFactor, thisCol
556+
UNPROTECT(nprotect); // ans, ansNames, coercedForFactor?
554557
return(ans);
555558
}

0 commit comments

Comments
 (0)