Macro for allocation in C
Clash Royale CLAN TAG#URR8PPP
$begingroup$
As we all know, the syntax of allocating memory is a bit clunky in C. The recommended way is:
int *p;
int n=10;
p = malloc(n*sizeof *p);
You can use sizeof (int)
instead of sizeof *p
but it is bad practice.
I made a solution to this with a macro:
#define ALLOC(p,n) do *p=malloc(n*sizeof **p); while(0)
This get called this way:
int *p;
int n=10;
ALLOC(&p, n);
The reason I want to pass the address of p rather than p, is to offer a bit of protection. When you call a function with foo(x)
, then foo
can never change the value of x
. If you're not passing the address, the argument will not change. (Sure there are ways around that too.)
Any comments?
c memory-management macros
$endgroup$
add a comment |
$begingroup$
As we all know, the syntax of allocating memory is a bit clunky in C. The recommended way is:
int *p;
int n=10;
p = malloc(n*sizeof *p);
You can use sizeof (int)
instead of sizeof *p
but it is bad practice.
I made a solution to this with a macro:
#define ALLOC(p,n) do *p=malloc(n*sizeof **p); while(0)
This get called this way:
int *p;
int n=10;
ALLOC(&p, n);
The reason I want to pass the address of p rather than p, is to offer a bit of protection. When you call a function with foo(x)
, then foo
can never change the value of x
. If you're not passing the address, the argument will not change. (Sure there are ways around that too.)
Any comments?
c memory-management macros
$endgroup$
$begingroup$
Please see What to do when someone answers. I have rolled back Rev 3 → 2.
$endgroup$
– 200_success
Jan 26 at 18:10
3
$begingroup$
I think the basic problem here is that your opinion of the "clunkiness" of C memory allocation is not shared by many experienced C programmers. (To me, it seems elegantly simple.) So by hiding what you're actually doing in a macro, you just introduce possible confusion.
$endgroup$
– jamesqf
Jan 27 at 5:18
add a comment |
$begingroup$
As we all know, the syntax of allocating memory is a bit clunky in C. The recommended way is:
int *p;
int n=10;
p = malloc(n*sizeof *p);
You can use sizeof (int)
instead of sizeof *p
but it is bad practice.
I made a solution to this with a macro:
#define ALLOC(p,n) do *p=malloc(n*sizeof **p); while(0)
This get called this way:
int *p;
int n=10;
ALLOC(&p, n);
The reason I want to pass the address of p rather than p, is to offer a bit of protection. When you call a function with foo(x)
, then foo
can never change the value of x
. If you're not passing the address, the argument will not change. (Sure there are ways around that too.)
Any comments?
c memory-management macros
$endgroup$
As we all know, the syntax of allocating memory is a bit clunky in C. The recommended way is:
int *p;
int n=10;
p = malloc(n*sizeof *p);
You can use sizeof (int)
instead of sizeof *p
but it is bad practice.
I made a solution to this with a macro:
#define ALLOC(p,n) do *p=malloc(n*sizeof **p); while(0)
This get called this way:
int *p;
int n=10;
ALLOC(&p, n);
The reason I want to pass the address of p rather than p, is to offer a bit of protection. When you call a function with foo(x)
, then foo
can never change the value of x
. If you're not passing the address, the argument will not change. (Sure there are ways around that too.)
Any comments?
c memory-management macros
c memory-management macros
edited Feb 4 at 12:46
Toby Speight
24.4k740114
24.4k740114
asked Jan 26 at 15:39
BromanBroman
24418
24418
$begingroup$
Please see What to do when someone answers. I have rolled back Rev 3 → 2.
$endgroup$
– 200_success
Jan 26 at 18:10
3
$begingroup$
I think the basic problem here is that your opinion of the "clunkiness" of C memory allocation is not shared by many experienced C programmers. (To me, it seems elegantly simple.) So by hiding what you're actually doing in a macro, you just introduce possible confusion.
$endgroup$
– jamesqf
Jan 27 at 5:18
add a comment |
$begingroup$
Please see What to do when someone answers. I have rolled back Rev 3 → 2.
$endgroup$
– 200_success
Jan 26 at 18:10
3
$begingroup$
I think the basic problem here is that your opinion of the "clunkiness" of C memory allocation is not shared by many experienced C programmers. (To me, it seems elegantly simple.) So by hiding what you're actually doing in a macro, you just introduce possible confusion.
$endgroup$
– jamesqf
Jan 27 at 5:18
$begingroup$
Please see What to do when someone answers. I have rolled back Rev 3 → 2.
$endgroup$
– 200_success
Jan 26 at 18:10
$begingroup$
Please see What to do when someone answers. I have rolled back Rev 3 → 2.
$endgroup$
– 200_success
Jan 26 at 18:10
3
3
$begingroup$
I think the basic problem here is that your opinion of the "clunkiness" of C memory allocation is not shared by many experienced C programmers. (To me, it seems elegantly simple.) So by hiding what you're actually doing in a macro, you just introduce possible confusion.
$endgroup$
– jamesqf
Jan 27 at 5:18
$begingroup$
I think the basic problem here is that your opinion of the "clunkiness" of C memory allocation is not shared by many experienced C programmers. (To me, it seems elegantly simple.) So by hiding what you're actually doing in a macro, you just introduce possible confusion.
$endgroup$
– jamesqf
Jan 27 at 5:18
add a comment |
4 Answers
4
active
oldest
votes
$begingroup$
p = malloc(n*sizeof *p);
This is dangerous if n
gets large, because the multiplication could overflow. After the overflow, too little memory has been allocated but code will continue without detecting the error.
This is especially dangerous if n
comes from untrusted source, such as some file format or remote user. Then it gives attacker easy way to overwrite parts of memory with exploit code.
The easy safe solution is to use calloc()
which will detect the overflow (at least on most common libc implementations). If you really need to use malloc()
for some reason, you can check for overflow separately.
$endgroup$
$begingroup$
Indeed, this is an often overlooked but very important point. I think that anycalloc
implementation that does not return a null pointer on overflow would not be conforming.
$endgroup$
– jamesdlin
Jan 26 at 23:38
1
$begingroup$
@jamesdlin Yes. Still, one should not ignore thatcalloc()
has to zero the memory too.
$endgroup$
– Deduplicator
Jan 26 at 23:43
add a comment |
$begingroup$
You've taken an expression statement and unnecessarily made a do/while
statement out of it. You need parentheses around your macro parameters. You don't need to pass in the pointer you're assigning to as a pointer.
Put all that together and you end up with:
#define ALLOC(p, n) ((p) = malloc((n) * sizeof *(p)))
This puts fewer restrictions on how it is used, and allows things like
struct monster *AddMonsters(monster *monsters, int which_monster, int how_many)
int difficulty_add = ExtraMonsters();
return ALLOC(monsters + which_monster, how_many + difficulty_add);
Yes, you could use monsters[which_monster]
, add the extra before using the macro, and put a separate return
statement, but all that would be unnecessary restrictions on its use.
$endgroup$
1
$begingroup$
The do-while is just something I always do with macros. A bit redundant here, but it does not hurt. Parenthesis I forgot. Thanks for that. But I do have a good reason for passing it as a pointer. See my edit.
$endgroup$
– Broman
Jan 26 at 17:18
5
$begingroup$
@Broman "Does not hurt"? Sure it does. You're unnecessarily making it illegal to use your macro where an expression is expected, such as withif (ALLOC(...))
.
$endgroup$
– jamesdlin
Jan 26 at 23:24
$begingroup$
@jamesdlin That's true. Thanks.
$endgroup$
– Broman
Jan 27 at 0:08
1
$begingroup$
I would prefer the do-while, personally. The body technically works as an expression, but it’s still an assignment. Those can be surprising in expression position, especially behind a macro.
$endgroup$
– gntskn
Jan 27 at 1:44
add a comment |
$begingroup$
There are a couple questionable things here, first since ALLOC()
is a macro you don't need to pass the address of p
. If ALLOC()
were a function call then you would want to pass the address of p
.
Second, for an array I would probably use calloc() rather than malloc().
$endgroup$
1
$begingroup$
The reason for passing the address is to make it clear that the argument will be modified.
$endgroup$
– Broman
Jan 26 at 17:54
add a comment |
$begingroup$
First of all, remove the unnecessary parts, which can cause errors and make the code harder to read.
#define ALLOC(p,n) p=malloc(n*sizeof *p)
You can make your code more readable with describing names. After months it will be quite hard to understand even your own code.
#define ALLOC(pointer, size) pointer = malloc(size * sizeof *pointer)
Parenthesizes are important! The following call: ALLOC(pointer, size + 1);
would be equal with pointer = malloc(size + 1 * sizeof *pointer);
, which clearly is a bug.
#define ALLOC(pointer, size) (pointer) = malloc((size) * sizeof(*pointer))
Use calloc
instead of malloc
, because of security reasons.
#define ALLOC(pointer, size) (pointer) = calloc((size), sizeof(*pointer))
Lastly, do not use function-like macros, instead a function would be a better choice.
https://rules.sonarsource.com/c/tag/preprocessor/RSPEC-960
$endgroup$
$begingroup$
"because of security reasons" is very vague, and arguably untrue. It's certainly not enough to justify an obvious pessimisation.
$endgroup$
– Toby Speight
Feb 4 at 12:48
$begingroup$
@jpa explained it quite well, so I did not went into details, but I focused on mentioning different, possible error sources.
$endgroup$
– Norbert Incze
Feb 4 at 14:38
add a comment |
Your Answer
StackExchange.ifUsing("editor", function ()
return StackExchange.using("mathjaxEditing", function ()
StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix)
StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
);
);
, "mathjax-editing");
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "196"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f212271%2fmacro-for-allocation-in-c%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
4 Answers
4
active
oldest
votes
4 Answers
4
active
oldest
votes
active
oldest
votes
active
oldest
votes
$begingroup$
p = malloc(n*sizeof *p);
This is dangerous if n
gets large, because the multiplication could overflow. After the overflow, too little memory has been allocated but code will continue without detecting the error.
This is especially dangerous if n
comes from untrusted source, such as some file format or remote user. Then it gives attacker easy way to overwrite parts of memory with exploit code.
The easy safe solution is to use calloc()
which will detect the overflow (at least on most common libc implementations). If you really need to use malloc()
for some reason, you can check for overflow separately.
$endgroup$
$begingroup$
Indeed, this is an often overlooked but very important point. I think that anycalloc
implementation that does not return a null pointer on overflow would not be conforming.
$endgroup$
– jamesdlin
Jan 26 at 23:38
1
$begingroup$
@jamesdlin Yes. Still, one should not ignore thatcalloc()
has to zero the memory too.
$endgroup$
– Deduplicator
Jan 26 at 23:43
add a comment |
$begingroup$
p = malloc(n*sizeof *p);
This is dangerous if n
gets large, because the multiplication could overflow. After the overflow, too little memory has been allocated but code will continue without detecting the error.
This is especially dangerous if n
comes from untrusted source, such as some file format or remote user. Then it gives attacker easy way to overwrite parts of memory with exploit code.
The easy safe solution is to use calloc()
which will detect the overflow (at least on most common libc implementations). If you really need to use malloc()
for some reason, you can check for overflow separately.
$endgroup$
$begingroup$
Indeed, this is an often overlooked but very important point. I think that anycalloc
implementation that does not return a null pointer on overflow would not be conforming.
$endgroup$
– jamesdlin
Jan 26 at 23:38
1
$begingroup$
@jamesdlin Yes. Still, one should not ignore thatcalloc()
has to zero the memory too.
$endgroup$
– Deduplicator
Jan 26 at 23:43
add a comment |
$begingroup$
p = malloc(n*sizeof *p);
This is dangerous if n
gets large, because the multiplication could overflow. After the overflow, too little memory has been allocated but code will continue without detecting the error.
This is especially dangerous if n
comes from untrusted source, such as some file format or remote user. Then it gives attacker easy way to overwrite parts of memory with exploit code.
The easy safe solution is to use calloc()
which will detect the overflow (at least on most common libc implementations). If you really need to use malloc()
for some reason, you can check for overflow separately.
$endgroup$
p = malloc(n*sizeof *p);
This is dangerous if n
gets large, because the multiplication could overflow. After the overflow, too little memory has been allocated but code will continue without detecting the error.
This is especially dangerous if n
comes from untrusted source, such as some file format or remote user. Then it gives attacker easy way to overwrite parts of memory with exploit code.
The easy safe solution is to use calloc()
which will detect the overflow (at least on most common libc implementations). If you really need to use malloc()
for some reason, you can check for overflow separately.
answered Jan 26 at 19:56
jpajpa
2412
2412
$begingroup$
Indeed, this is an often overlooked but very important point. I think that anycalloc
implementation that does not return a null pointer on overflow would not be conforming.
$endgroup$
– jamesdlin
Jan 26 at 23:38
1
$begingroup$
@jamesdlin Yes. Still, one should not ignore thatcalloc()
has to zero the memory too.
$endgroup$
– Deduplicator
Jan 26 at 23:43
add a comment |
$begingroup$
Indeed, this is an often overlooked but very important point. I think that anycalloc
implementation that does not return a null pointer on overflow would not be conforming.
$endgroup$
– jamesdlin
Jan 26 at 23:38
1
$begingroup$
@jamesdlin Yes. Still, one should not ignore thatcalloc()
has to zero the memory too.
$endgroup$
– Deduplicator
Jan 26 at 23:43
$begingroup$
Indeed, this is an often overlooked but very important point. I think that any
calloc
implementation that does not return a null pointer on overflow would not be conforming.$endgroup$
– jamesdlin
Jan 26 at 23:38
$begingroup$
Indeed, this is an often overlooked but very important point. I think that any
calloc
implementation that does not return a null pointer on overflow would not be conforming.$endgroup$
– jamesdlin
Jan 26 at 23:38
1
1
$begingroup$
@jamesdlin Yes. Still, one should not ignore that
calloc()
has to zero the memory too.$endgroup$
– Deduplicator
Jan 26 at 23:43
$begingroup$
@jamesdlin Yes. Still, one should not ignore that
calloc()
has to zero the memory too.$endgroup$
– Deduplicator
Jan 26 at 23:43
add a comment |
$begingroup$
You've taken an expression statement and unnecessarily made a do/while
statement out of it. You need parentheses around your macro parameters. You don't need to pass in the pointer you're assigning to as a pointer.
Put all that together and you end up with:
#define ALLOC(p, n) ((p) = malloc((n) * sizeof *(p)))
This puts fewer restrictions on how it is used, and allows things like
struct monster *AddMonsters(monster *monsters, int which_monster, int how_many)
int difficulty_add = ExtraMonsters();
return ALLOC(monsters + which_monster, how_many + difficulty_add);
Yes, you could use monsters[which_monster]
, add the extra before using the macro, and put a separate return
statement, but all that would be unnecessary restrictions on its use.
$endgroup$
1
$begingroup$
The do-while is just something I always do with macros. A bit redundant here, but it does not hurt. Parenthesis I forgot. Thanks for that. But I do have a good reason for passing it as a pointer. See my edit.
$endgroup$
– Broman
Jan 26 at 17:18
5
$begingroup$
@Broman "Does not hurt"? Sure it does. You're unnecessarily making it illegal to use your macro where an expression is expected, such as withif (ALLOC(...))
.
$endgroup$
– jamesdlin
Jan 26 at 23:24
$begingroup$
@jamesdlin That's true. Thanks.
$endgroup$
– Broman
Jan 27 at 0:08
1
$begingroup$
I would prefer the do-while, personally. The body technically works as an expression, but it’s still an assignment. Those can be surprising in expression position, especially behind a macro.
$endgroup$
– gntskn
Jan 27 at 1:44
add a comment |
$begingroup$
You've taken an expression statement and unnecessarily made a do/while
statement out of it. You need parentheses around your macro parameters. You don't need to pass in the pointer you're assigning to as a pointer.
Put all that together and you end up with:
#define ALLOC(p, n) ((p) = malloc((n) * sizeof *(p)))
This puts fewer restrictions on how it is used, and allows things like
struct monster *AddMonsters(monster *monsters, int which_monster, int how_many)
int difficulty_add = ExtraMonsters();
return ALLOC(monsters + which_monster, how_many + difficulty_add);
Yes, you could use monsters[which_monster]
, add the extra before using the macro, and put a separate return
statement, but all that would be unnecessary restrictions on its use.
$endgroup$
1
$begingroup$
The do-while is just something I always do with macros. A bit redundant here, but it does not hurt. Parenthesis I forgot. Thanks for that. But I do have a good reason for passing it as a pointer. See my edit.
$endgroup$
– Broman
Jan 26 at 17:18
5
$begingroup$
@Broman "Does not hurt"? Sure it does. You're unnecessarily making it illegal to use your macro where an expression is expected, such as withif (ALLOC(...))
.
$endgroup$
– jamesdlin
Jan 26 at 23:24
$begingroup$
@jamesdlin That's true. Thanks.
$endgroup$
– Broman
Jan 27 at 0:08
1
$begingroup$
I would prefer the do-while, personally. The body technically works as an expression, but it’s still an assignment. Those can be surprising in expression position, especially behind a macro.
$endgroup$
– gntskn
Jan 27 at 1:44
add a comment |
$begingroup$
You've taken an expression statement and unnecessarily made a do/while
statement out of it. You need parentheses around your macro parameters. You don't need to pass in the pointer you're assigning to as a pointer.
Put all that together and you end up with:
#define ALLOC(p, n) ((p) = malloc((n) * sizeof *(p)))
This puts fewer restrictions on how it is used, and allows things like
struct monster *AddMonsters(monster *monsters, int which_monster, int how_many)
int difficulty_add = ExtraMonsters();
return ALLOC(monsters + which_monster, how_many + difficulty_add);
Yes, you could use monsters[which_monster]
, add the extra before using the macro, and put a separate return
statement, but all that would be unnecessary restrictions on its use.
$endgroup$
You've taken an expression statement and unnecessarily made a do/while
statement out of it. You need parentheses around your macro parameters. You don't need to pass in the pointer you're assigning to as a pointer.
Put all that together and you end up with:
#define ALLOC(p, n) ((p) = malloc((n) * sizeof *(p)))
This puts fewer restrictions on how it is used, and allows things like
struct monster *AddMonsters(monster *monsters, int which_monster, int how_many)
int difficulty_add = ExtraMonsters();
return ALLOC(monsters + which_monster, how_many + difficulty_add);
Yes, you could use monsters[which_monster]
, add the extra before using the macro, and put a separate return
statement, but all that would be unnecessary restrictions on its use.
answered Jan 26 at 16:59
1201ProgramAlarm1201ProgramAlarm
3,2082823
3,2082823
1
$begingroup$
The do-while is just something I always do with macros. A bit redundant here, but it does not hurt. Parenthesis I forgot. Thanks for that. But I do have a good reason for passing it as a pointer. See my edit.
$endgroup$
– Broman
Jan 26 at 17:18
5
$begingroup$
@Broman "Does not hurt"? Sure it does. You're unnecessarily making it illegal to use your macro where an expression is expected, such as withif (ALLOC(...))
.
$endgroup$
– jamesdlin
Jan 26 at 23:24
$begingroup$
@jamesdlin That's true. Thanks.
$endgroup$
– Broman
Jan 27 at 0:08
1
$begingroup$
I would prefer the do-while, personally. The body technically works as an expression, but it’s still an assignment. Those can be surprising in expression position, especially behind a macro.
$endgroup$
– gntskn
Jan 27 at 1:44
add a comment |
1
$begingroup$
The do-while is just something I always do with macros. A bit redundant here, but it does not hurt. Parenthesis I forgot. Thanks for that. But I do have a good reason for passing it as a pointer. See my edit.
$endgroup$
– Broman
Jan 26 at 17:18
5
$begingroup$
@Broman "Does not hurt"? Sure it does. You're unnecessarily making it illegal to use your macro where an expression is expected, such as withif (ALLOC(...))
.
$endgroup$
– jamesdlin
Jan 26 at 23:24
$begingroup$
@jamesdlin That's true. Thanks.
$endgroup$
– Broman
Jan 27 at 0:08
1
$begingroup$
I would prefer the do-while, personally. The body technically works as an expression, but it’s still an assignment. Those can be surprising in expression position, especially behind a macro.
$endgroup$
– gntskn
Jan 27 at 1:44
1
1
$begingroup$
The do-while is just something I always do with macros. A bit redundant here, but it does not hurt. Parenthesis I forgot. Thanks for that. But I do have a good reason for passing it as a pointer. See my edit.
$endgroup$
– Broman
Jan 26 at 17:18
$begingroup$
The do-while is just something I always do with macros. A bit redundant here, but it does not hurt. Parenthesis I forgot. Thanks for that. But I do have a good reason for passing it as a pointer. See my edit.
$endgroup$
– Broman
Jan 26 at 17:18
5
5
$begingroup$
@Broman "Does not hurt"? Sure it does. You're unnecessarily making it illegal to use your macro where an expression is expected, such as with
if (ALLOC(...))
.$endgroup$
– jamesdlin
Jan 26 at 23:24
$begingroup$
@Broman "Does not hurt"? Sure it does. You're unnecessarily making it illegal to use your macro where an expression is expected, such as with
if (ALLOC(...))
.$endgroup$
– jamesdlin
Jan 26 at 23:24
$begingroup$
@jamesdlin That's true. Thanks.
$endgroup$
– Broman
Jan 27 at 0:08
$begingroup$
@jamesdlin That's true. Thanks.
$endgroup$
– Broman
Jan 27 at 0:08
1
1
$begingroup$
I would prefer the do-while, personally. The body technically works as an expression, but it’s still an assignment. Those can be surprising in expression position, especially behind a macro.
$endgroup$
– gntskn
Jan 27 at 1:44
$begingroup$
I would prefer the do-while, personally. The body technically works as an expression, but it’s still an assignment. Those can be surprising in expression position, especially behind a macro.
$endgroup$
– gntskn
Jan 27 at 1:44
add a comment |
$begingroup$
There are a couple questionable things here, first since ALLOC()
is a macro you don't need to pass the address of p
. If ALLOC()
were a function call then you would want to pass the address of p
.
Second, for an array I would probably use calloc() rather than malloc().
$endgroup$
1
$begingroup$
The reason for passing the address is to make it clear that the argument will be modified.
$endgroup$
– Broman
Jan 26 at 17:54
add a comment |
$begingroup$
There are a couple questionable things here, first since ALLOC()
is a macro you don't need to pass the address of p
. If ALLOC()
were a function call then you would want to pass the address of p
.
Second, for an array I would probably use calloc() rather than malloc().
$endgroup$
1
$begingroup$
The reason for passing the address is to make it clear that the argument will be modified.
$endgroup$
– Broman
Jan 26 at 17:54
add a comment |
$begingroup$
There are a couple questionable things here, first since ALLOC()
is a macro you don't need to pass the address of p
. If ALLOC()
were a function call then you would want to pass the address of p
.
Second, for an array I would probably use calloc() rather than malloc().
$endgroup$
There are a couple questionable things here, first since ALLOC()
is a macro you don't need to pass the address of p
. If ALLOC()
were a function call then you would want to pass the address of p
.
Second, for an array I would probably use calloc() rather than malloc().
answered Jan 26 at 16:17
pacmaninbwpacmaninbw
5,15321537
5,15321537
1
$begingroup$
The reason for passing the address is to make it clear that the argument will be modified.
$endgroup$
– Broman
Jan 26 at 17:54
add a comment |
1
$begingroup$
The reason for passing the address is to make it clear that the argument will be modified.
$endgroup$
– Broman
Jan 26 at 17:54
1
1
$begingroup$
The reason for passing the address is to make it clear that the argument will be modified.
$endgroup$
– Broman
Jan 26 at 17:54
$begingroup$
The reason for passing the address is to make it clear that the argument will be modified.
$endgroup$
– Broman
Jan 26 at 17:54
add a comment |
$begingroup$
First of all, remove the unnecessary parts, which can cause errors and make the code harder to read.
#define ALLOC(p,n) p=malloc(n*sizeof *p)
You can make your code more readable with describing names. After months it will be quite hard to understand even your own code.
#define ALLOC(pointer, size) pointer = malloc(size * sizeof *pointer)
Parenthesizes are important! The following call: ALLOC(pointer, size + 1);
would be equal with pointer = malloc(size + 1 * sizeof *pointer);
, which clearly is a bug.
#define ALLOC(pointer, size) (pointer) = malloc((size) * sizeof(*pointer))
Use calloc
instead of malloc
, because of security reasons.
#define ALLOC(pointer, size) (pointer) = calloc((size), sizeof(*pointer))
Lastly, do not use function-like macros, instead a function would be a better choice.
https://rules.sonarsource.com/c/tag/preprocessor/RSPEC-960
$endgroup$
$begingroup$
"because of security reasons" is very vague, and arguably untrue. It's certainly not enough to justify an obvious pessimisation.
$endgroup$
– Toby Speight
Feb 4 at 12:48
$begingroup$
@jpa explained it quite well, so I did not went into details, but I focused on mentioning different, possible error sources.
$endgroup$
– Norbert Incze
Feb 4 at 14:38
add a comment |
$begingroup$
First of all, remove the unnecessary parts, which can cause errors and make the code harder to read.
#define ALLOC(p,n) p=malloc(n*sizeof *p)
You can make your code more readable with describing names. After months it will be quite hard to understand even your own code.
#define ALLOC(pointer, size) pointer = malloc(size * sizeof *pointer)
Parenthesizes are important! The following call: ALLOC(pointer, size + 1);
would be equal with pointer = malloc(size + 1 * sizeof *pointer);
, which clearly is a bug.
#define ALLOC(pointer, size) (pointer) = malloc((size) * sizeof(*pointer))
Use calloc
instead of malloc
, because of security reasons.
#define ALLOC(pointer, size) (pointer) = calloc((size), sizeof(*pointer))
Lastly, do not use function-like macros, instead a function would be a better choice.
https://rules.sonarsource.com/c/tag/preprocessor/RSPEC-960
$endgroup$
$begingroup$
"because of security reasons" is very vague, and arguably untrue. It's certainly not enough to justify an obvious pessimisation.
$endgroup$
– Toby Speight
Feb 4 at 12:48
$begingroup$
@jpa explained it quite well, so I did not went into details, but I focused on mentioning different, possible error sources.
$endgroup$
– Norbert Incze
Feb 4 at 14:38
add a comment |
$begingroup$
First of all, remove the unnecessary parts, which can cause errors and make the code harder to read.
#define ALLOC(p,n) p=malloc(n*sizeof *p)
You can make your code more readable with describing names. After months it will be quite hard to understand even your own code.
#define ALLOC(pointer, size) pointer = malloc(size * sizeof *pointer)
Parenthesizes are important! The following call: ALLOC(pointer, size + 1);
would be equal with pointer = malloc(size + 1 * sizeof *pointer);
, which clearly is a bug.
#define ALLOC(pointer, size) (pointer) = malloc((size) * sizeof(*pointer))
Use calloc
instead of malloc
, because of security reasons.
#define ALLOC(pointer, size) (pointer) = calloc((size), sizeof(*pointer))
Lastly, do not use function-like macros, instead a function would be a better choice.
https://rules.sonarsource.com/c/tag/preprocessor/RSPEC-960
$endgroup$
First of all, remove the unnecessary parts, which can cause errors and make the code harder to read.
#define ALLOC(p,n) p=malloc(n*sizeof *p)
You can make your code more readable with describing names. After months it will be quite hard to understand even your own code.
#define ALLOC(pointer, size) pointer = malloc(size * sizeof *pointer)
Parenthesizes are important! The following call: ALLOC(pointer, size + 1);
would be equal with pointer = malloc(size + 1 * sizeof *pointer);
, which clearly is a bug.
#define ALLOC(pointer, size) (pointer) = malloc((size) * sizeof(*pointer))
Use calloc
instead of malloc
, because of security reasons.
#define ALLOC(pointer, size) (pointer) = calloc((size), sizeof(*pointer))
Lastly, do not use function-like macros, instead a function would be a better choice.
https://rules.sonarsource.com/c/tag/preprocessor/RSPEC-960
answered Feb 2 at 17:53
Norbert InczeNorbert Incze
1
1
$begingroup$
"because of security reasons" is very vague, and arguably untrue. It's certainly not enough to justify an obvious pessimisation.
$endgroup$
– Toby Speight
Feb 4 at 12:48
$begingroup$
@jpa explained it quite well, so I did not went into details, but I focused on mentioning different, possible error sources.
$endgroup$
– Norbert Incze
Feb 4 at 14:38
add a comment |
$begingroup$
"because of security reasons" is very vague, and arguably untrue. It's certainly not enough to justify an obvious pessimisation.
$endgroup$
– Toby Speight
Feb 4 at 12:48
$begingroup$
@jpa explained it quite well, so I did not went into details, but I focused on mentioning different, possible error sources.
$endgroup$
– Norbert Incze
Feb 4 at 14:38
$begingroup$
"because of security reasons" is very vague, and arguably untrue. It's certainly not enough to justify an obvious pessimisation.
$endgroup$
– Toby Speight
Feb 4 at 12:48
$begingroup$
"because of security reasons" is very vague, and arguably untrue. It's certainly not enough to justify an obvious pessimisation.
$endgroup$
– Toby Speight
Feb 4 at 12:48
$begingroup$
@jpa explained it quite well, so I did not went into details, but I focused on mentioning different, possible error sources.
$endgroup$
– Norbert Incze
Feb 4 at 14:38
$begingroup$
@jpa explained it quite well, so I did not went into details, but I focused on mentioning different, possible error sources.
$endgroup$
– Norbert Incze
Feb 4 at 14:38
add a comment |
Thanks for contributing an answer to Code Review Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
Use MathJax to format equations. MathJax reference.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f212271%2fmacro-for-allocation-in-c%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
$begingroup$
Please see What to do when someone answers. I have rolled back Rev 3 → 2.
$endgroup$
– 200_success
Jan 26 at 18:10
3
$begingroup$
I think the basic problem here is that your opinion of the "clunkiness" of C memory allocation is not shared by many experienced C programmers. (To me, it seems elegantly simple.) So by hiding what you're actually doing in a macro, you just introduce possible confusion.
$endgroup$
– jamesqf
Jan 27 at 5:18