Skip to content

Commit b1505e4

Browse files
committed
pythongh-127635: Use flexible array in tracemalloc
Replace frames[1] with frames[] in tracemalloc_traceback structure.
1 parent 9ac1428 commit b1505e4

File tree

2 files changed

+30
-16
lines changed

2 files changed

+30
-16
lines changed

Include/internal/pycore_tracemalloc.h

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ struct _PyTraceMalloc_Config {
3030
};
3131

3232

33-
/* Pack the frame_t structure to reduce the memory footprint on 64-bit
34-
architectures: 12 bytes instead of 16. */
33+
/* Pack the tracemalloc_frame and tracemalloc_traceback structures to reduce
34+
the memory footprint on 64-bit architectures: 12 bytes instead of 16. */
3535
#if defined(_MSC_VER)
3636
#pragma pack(push, 4)
3737
#endif
@@ -46,18 +46,22 @@ tracemalloc_frame {
4646
PyObject *filename;
4747
unsigned int lineno;
4848
};
49-
#ifdef _MSC_VER
50-
#pragma pack(pop)
51-
#endif
5249

53-
struct tracemalloc_traceback {
50+
struct
51+
#ifdef __GNUC__
52+
__attribute__((packed))
53+
#endif
54+
tracemalloc_traceback {
5455
Py_uhash_t hash;
5556
/* Number of frames stored */
5657
uint16_t nframe;
5758
/* Total number of frames the traceback had */
5859
uint16_t total_nframe;
59-
struct tracemalloc_frame frames[1];
60+
struct tracemalloc_frame frames[];
6061
};
62+
#ifdef _MSC_VER
63+
#pragma pack(pop)
64+
#endif
6165

6266

6367
struct _tracemalloc_runtime_state {
@@ -95,7 +99,7 @@ struct _tracemalloc_runtime_state {
9599
Protected by TABLES_LOCK(). */
96100
_Py_hashtable_t *domains;
97101

98-
struct tracemalloc_traceback empty_traceback;
102+
struct tracemalloc_traceback *empty_traceback;
99103

100104
Py_tss_t reentrant_key;
101105
};

Python/tracemalloc.c

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ typedef struct tracemalloc_frame frame_t;
4646
typedef struct tracemalloc_traceback traceback_t;
4747

4848
#define TRACEBACK_SIZE(NFRAME) \
49-
(sizeof(traceback_t) + sizeof(frame_t) * (NFRAME - 1))
49+
(sizeof(traceback_t) + sizeof(frame_t) * (NFRAME))
5050

5151
static const int MAX_NFRAME = UINT16_MAX;
5252

@@ -329,8 +329,9 @@ traceback_new(void)
329329
traceback->nframe = 0;
330330
traceback->total_nframe = 0;
331331
traceback_get_frames(traceback);
332-
if (traceback->nframe == 0)
333-
return &tracemalloc_empty_traceback;
332+
if (traceback->nframe == 0) {
333+
return tracemalloc_empty_traceback;
334+
}
334335
traceback->hash = traceback_hash(traceback);
335336

336337
/* intern the traceback */
@@ -754,12 +755,18 @@ _PyTraceMalloc_Init(void)
754755
return _PyStatus_NO_MEMORY();
755756
}
756757

757-
tracemalloc_empty_traceback.nframe = 1;
758-
tracemalloc_empty_traceback.total_nframe = 1;
758+
assert(tracemalloc_empty_traceback == NULL);
759+
tracemalloc_empty_traceback = raw_malloc(TRACEBACK_SIZE(1));
760+
if (tracemalloc_empty_traceback == NULL) {
761+
return _PyStatus_NO_MEMORY();
762+
}
763+
764+
tracemalloc_empty_traceback->nframe = 1;
765+
tracemalloc_empty_traceback->total_nframe = 1;
759766
/* borrowed reference */
760-
tracemalloc_empty_traceback.frames[0].filename = &_Py_STR(anon_unknown);
761-
tracemalloc_empty_traceback.frames[0].lineno = 0;
762-
tracemalloc_empty_traceback.hash = traceback_hash(&tracemalloc_empty_traceback);
767+
tracemalloc_empty_traceback->frames[0].filename = &_Py_STR(anon_unknown);
768+
tracemalloc_empty_traceback->frames[0].lineno = 0;
769+
tracemalloc_empty_traceback->hash = traceback_hash(tracemalloc_empty_traceback);
763770

764771
tracemalloc_config.initialized = TRACEMALLOC_INITIALIZED;
765772
return _PyStatus_OK();
@@ -782,6 +789,9 @@ tracemalloc_deinit(void)
782789
_Py_hashtable_destroy(tracemalloc_filenames);
783790

784791
PyThread_tss_delete(&tracemalloc_reentrant_key);
792+
793+
raw_free(tracemalloc_empty_traceback);
794+
tracemalloc_empty_traceback = NULL;
785795
}
786796

787797

0 commit comments

Comments
 (0)