Skip to content

Commit af6e637

Browse files
xunicattQuuxplusone
authored andcommitted
[utarray] Add utarray_replace macro to safely replace elements (#272)
Introduces a new macro function utarray_replace in utarray.h, which enables safe replacement of an element in a UT_array. Currently, modifying an element in a UT_array often involves retrieving a pointer via utarray_eltptr and then directly assigning a new value. However, this method bypasses any user-defined ctor or dtor functions, potentially leading to memory leaks or undefined behavior when managing complex data types. The new utarray_replace macro ensures that when an element is replaced: - The existing element is properly destroyed using the dtor, if defined. - The new element is constructed via the ctor, if defined.
1 parent 64f8676 commit af6e637

File tree

7 files changed

+106
-1
lines changed

7 files changed

+106
-1
lines changed

doc/utarray.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,7 @@ Operations
325325
| utarray_eltptr(UT_array *a,int j) | get pointer of element from index
326326
| utarray_eltidx(UT_array *a,void *e) | get index of element from pointer
327327
| utarray_insert(UT_array *a,void *p, int j) | insert element p to index j
328+
| utarray_replace(UT_array *a,void *p, int j) | replace element p at index j
328329
| utarray_inserta(UT_array *a,UT_array *w, int j) | insert array w into array a at index j
329330
| utarray_resize(UT_array *dst,int num) | extend or shrink array to num elements
330331
| utarray_concat(UT_array *dst,UT_array *src) | copy src to end of dst array

src/utarray.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,12 @@ typedef struct {
136136
(a)->i++; \
137137
} while(0)
138138

139+
#define utarray_replace(a,p,j) do { \
140+
if ((a)->icd.dtor) { (a)->icd.dtor(_utarray_eltptr(a,j)); } \
141+
if ((a)->icd.copy) { (a)->icd.copy(_utarray_eltptr(a,j), p); } \
142+
else { memcpy(_utarray_eltptr(a,j), p, (a)->icd.sz); } \
143+
} while(0)
144+
139145
#define utarray_inserta(a,w,j) do { \
140146
if (utarray_len(w) == 0) break; \
141147
if ((j) > (a)->i) utarray_resize(a,j); \

tests/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ PROGS = test1 test2 test3 test4 test5 test6 test7 test8 test9 \
1313
test74 test75 test76 test77 test78 test79 test80 test81 \
1414
test82 test83 test84 test85 test86 test87 test88 test89 \
1515
test90 test91 test92 test93 test94 test95 test96 test97 \
16-
test98
16+
test98 test99 test100
1717
CFLAGS += -I$(HASHDIR)
1818
#CFLAGS += -DHASH_BLOOM=16
1919
#CFLAGS += -O2

tests/test100.ans

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
id: 0 dept: A
2+
id: 1 dept: B
3+
id: 2 dept: C
4+
id: 3 dept: D
5+
id: 4 dept: E
6+
id: 25 dept: Z
7+
id: 6 dept: G
8+
id: 7 dept: H
9+
id: 8 dept: I
10+
id: 9 dept: J

tests/test100.c

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
#include <stdlib.h>
2+
#include <stdio.h>
3+
#include <string.h>
4+
#include "utarray.h"
5+
6+
typedef struct {
7+
int id;
8+
char *dept;
9+
} Data;
10+
11+
void Data_copy(void* vdst, const void* vsrc) {
12+
Data *dst = (Data*)vdst;
13+
Data *src = (Data*)vsrc;
14+
dst->id = src->id;
15+
dst->dept = strdup(src->dept);
16+
}
17+
18+
void Data_deinit(void* vdata) {
19+
Data *data = (Data*)vdata;
20+
free(data->dept);
21+
}
22+
23+
int main(void) {
24+
UT_array *datas;
25+
int i;
26+
Data d, *dp;
27+
char tmp[2] = "A";
28+
29+
UT_icd data_icd = {sizeof(Data), NULL, Data_copy, Data_deinit};
30+
utarray_new(datas, &data_icd);
31+
32+
for(i = 0; i < 10; i++) {
33+
d.id = i;
34+
d.dept = strdup(tmp);
35+
utarray_push_back(datas, &d);
36+
Data_deinit(&d);
37+
tmp[0] += 1;
38+
}
39+
40+
d.id = 25;
41+
d.dept = strdup("Z");
42+
utarray_replace(datas, &d, 5);
43+
Data_deinit(&d);
44+
45+
for(dp = (Data*)utarray_front(datas);
46+
dp != NULL;
47+
dp = (Data*)utarray_next(datas, dp)) {
48+
printf("id: %d dept: %s\n", dp->id, dp->dept);
49+
}
50+
51+
utarray_free(datas);
52+
return 0;
53+
}

tests/test99.ans

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
1
2+
2
3+
4
4+
8
5+
16
6+
110
7+
64
8+
128
9+
256
10+
512

tests/test99.c

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#include <stdio.h>
2+
#include "utarray.h"
3+
4+
int main(void) {
5+
UT_array *nums;
6+
int i, *p;
7+
8+
utarray_new(nums, &ut_int_icd);
9+
10+
for(i = 1; i < 1024; i <<= 1){
11+
utarray_push_back(nums, &i);
12+
}
13+
14+
i = 110;
15+
utarray_replace(nums, &i, 5);
16+
17+
for(p = (int*)utarray_front(nums);
18+
p != NULL;
19+
p = (int*)utarray_next(nums, p)) {
20+
printf("%d\n",*p);
21+
}
22+
23+
utarray_free(nums);
24+
return 0;
25+
}

0 commit comments

Comments
 (0)