Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #142084 > unrolled thread

heap memory indexed as an array

Started bysinbad <sinbad.sinbad@gmail.com>
First post2019-03-19 20:05 -0700
Last post2019-03-20 12:12 +0000
Articles 17 — 12 participants

Back to article view | Back to comp.lang.c


Contents

  heap memory indexed as an array sinbad <sinbad.sinbad@gmail.com> - 2019-03-19 20:05 -0700
    Re: heap memory indexed as an array Joe Pfeiffer <pfeiffer@cs.nmsu.edu> - 2019-03-19 21:37 -0600
      Re: heap memory indexed as an array Spiros Bousbouras <spibou@gmail.com> - 2019-03-20 04:40 +0000
        Re: heap memory indexed as an array nobody@example.org (Scott) - 2019-03-20 15:56 +0000
          Re: heap memory indexed as an array scott@slp53.sl.home (Scott Lurndal) - 2019-03-20 16:43 +0000
            Re: heap memory indexed as an array fir <profesor.fir@gmail.com> - 2019-03-20 10:00 -0700
            Re: heap memory indexed as an array William Ahern <william@25thandClement.com> - 2019-03-20 15:07 -0700
              Re: heap memory indexed as an array fir is a sexy shemale <cdalten@gmail.com> - 2019-03-20 23:52 -0700
            Re: heap memory indexed as an array nobody@example.org (Scott) - 2019-03-21 16:50 +0000
              Re: heap memory indexed as an array scott@slp53.sl.home (Scott Lurndal) - 2019-03-21 17:23 +0000
                Re: heap memory indexed as an array nobody@example.org (Scott) - 2019-03-22 04:29 +0000
                  OT: crashing malloc [was Re: heap memory indexed as an array] nobody@example.org (Scott) - 2019-03-23 15:27 +0000
                  Re: heap memory indexed as an array Spiros Bousbouras <spibou@gmail.com> - 2019-03-23 19:24 +0000
                    Re: heap memory indexed as an array Melzzzzz <Melzzzzz@zzzzz.com> - 2019-03-23 20:20 +0000
        Re: heap memory indexed as an array Tim Rentsch <tr.17687@z991.linuxsc.com> - 2019-03-21 22:35 -0700
    Re: heap memory indexed as an array Jorgen Grahn <grahn+nntp@snipabacken.se> - 2019-03-20 07:05 +0000
    Re: heap memory indexed as an array Ben Bacarisse <ben.usenet@bsb.me.uk> - 2019-03-20 12:12 +0000

#142084 — heap memory indexed as an array

Fromsinbad <sinbad.sinbad@gmail.com>
Date2019-03-19 20:05 -0700
Subjectheap memory indexed as an array
Message-ID<5b6ce6dd-178a-4fb6-9d80-af5349c0cec2@googlegroups.com>
Hi,

Is it safe to use heap memory as an array?

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

typedef struct cell {
    char name[5];
    int y;
} cell_t;

#define MAX_CELLS 5

int main() {
    int i;
    cell_t *p;

    p = calloc(MAX_CELLS, sizeof(cell_t));

    for (i = 0; i < MAX_CELLS; i++) {
        strcpy(p[i * sizeof(cell_t)].name, "test");
        p[i * sizeof(cell_t)].y = i;
    }

    for (i = 0; i < MAX_CELLS; i++) {
        printf("%s %u\n", p[i * sizeof(cell_t)].name,
               p[i*sizeof(cell_t)].y);
    }

    free(p);
    return 0;

}

[toc] | [next] | [standalone]


#142085

FromJoe Pfeiffer <pfeiffer@cs.nmsu.edu>
Date2019-03-19 21:37 -0600
Message-ID<1bk1gu8bdp.fsf@pfeifferfamily.net>
In reply to#142084
sinbad <sinbad.sinbad@gmail.com> writes:

> Hi,
>
> Is it safe to use heap memory as an array?
>
> #include <stdio.h>
> #include <string.h>
> #include <stdlib.h>
>
> typedef struct cell {
>     char name[5];
>     int y;
> } cell_t;
>
> #define MAX_CELLS 5
>
> int main() {
>     int i;
>     cell_t *p;
>
>     p = calloc(MAX_CELLS, sizeof(cell_t));
>
>     for (i = 0; i < MAX_CELLS; i++) {
>         strcpy(p[i * sizeof(cell_t)].name, "test");
>         p[i * sizeof(cell_t)].y = i;
>     }
>
>     for (i = 0; i < MAX_CELLS; i++) {
>         printf("%s %u\n", p[i * sizeof(cell_t)].name,
>                p[i*sizeof(cell_t)].y);
>     }
>
>     free(p);
>     return 0;
>
> }

Not only is it OK to use dynamically allocated memory with an index
("like an array"), it's easier than your code indicates.

You don't need to multiply the index by the cell size -- the compiler
does that for you.

         printf("%s %u\n", p[i].name,

will work in your printf().

It's actually even easier than that.  Assuming you don't know how many
cells you need at compile time, you can simply use a variable length
array, and say

cell_t p[number_of_cells];

(you also don't need to free in this case)

In your particular example, of course, it isn't even a variable length
array since MAX_CELLS is a constant known at compile time.

[toc] | [prev] | [next] | [standalone]


#142086

FromSpiros Bousbouras <spibou@gmail.com>
Date2019-03-20 04:40 +0000
Message-ID<aDpYuPXgbPvO0TB2QttltgH9QFlBQ@bongo-ra.co>
In reply to#142085
On Tue, 19 Mar 2019 21:37:06 -0600
Joe Pfeiffer <pfeiffer@cs.nmsu.edu> wrote:
> sinbad <sinbad.sinbad@gmail.com> writes:
> 
> > Hi,
> >
> > Is it safe to use heap memory as an array?
> >
> > #include <stdio.h>
> > #include <string.h>
> > #include <stdlib.h>
> >
> > typedef struct cell {
> >     char name[5];
> >     int y;
> > } cell_t;
> >
> > #define MAX_CELLS 5
> >
> > int main() {
> >     int i;
> >     cell_t *p;
> >
> >     p = calloc(MAX_CELLS, sizeof(cell_t));

    if (p == 0) return EXIT_FAILURE ;

> >
> >     for (i = 0; i < MAX_CELLS; i++) {
> >         strcpy(p[i * sizeof(cell_t)].name, "test");
> >         p[i * sizeof(cell_t)].y = i;
> >     }
> >
> >     for (i = 0; i < MAX_CELLS; i++) {
> >         printf("%s %u\n", p[i * sizeof(cell_t)].name,
> >                p[i*sizeof(cell_t)].y);
> >     }
> >
> >     free(p);
> >     return 0;
> >
> > }
> 
> Not only is it OK to use dynamically allocated memory with an index
> ("like an array"), it's easier than your code indicates.
> 
> You don't need to multiply the index by the cell size -- the compiler
> does that for you.
> 
>          printf("%s %u\n", p[i].name,
> 
> will work in your printf().

That depends on what the full  printf() invocation says. The obvious
extrapolation from the original code would be
    printf("%s %u\n", p[i].name, p[i].y) ;

but this is undefined behaviour because  p[i].y  has type  int  whereas
%u  is for  unsigned int .On the other hand either of
    printf("%s %u\n", p[i].name, (unsigned int) p[i].y) ;
or
    printf("%s %d\n", p[i].name, p[i].y) ;

would work.

> It's actually even easier than that.  Assuming you don't know how many
> cells you need at compile time, you can simply use a variable length
> array, and say
> 
> cell_t p[number_of_cells];
> 
> (you also don't need to free in this case)

But you don't get to do error checking either and if there isn't enough
memory to allocate the array , the programme will probably crash with an
uninformative error message.

> In your particular example, of course, it isn't even a variable length
> array since MAX_CELLS is a constant known at compile time.

[toc] | [prev] | [next] | [standalone]


#142106

Fromnobody@example.org (Scott)
Date2019-03-20 15:56 +0000
Message-ID<5c925e27.171165954@news.xmission.com>
In reply to#142086
On Wed, 20 Mar 2019 04:40:25 GMT, Spiros Bousbouras <spibou@gmail.com>
wrote:

>But you don't get to do error checking either and if there isn't enough
>memory to allocate the array , the programme will probably crash with an
>uninformative error message.

Well, maybe. On some contemporary operating systems, a malloc return
value of non-null does not guarantee that the allocated memory
actually exists. It can appear to succeed, and only explodes when you
try to write to that phantom memory -- and there's no way to trap that
fault in C.

That's not C's fault of course, just something to keep in mind as a C
wright.

I'm not sure how this state of affairs came to be, other than some
misguided pandering to sloppy and lazy programmers. But it seems to be
the new normal. It has one positive(?) side effect, in that you can
usually disable this "feature" in the OS, and this works to rapidly
identify programs written by sloppy and lazy programmers as they begin
spewing ENOMEM faults.

And this is off-topic in CLC. But yes, you can use heap as an array,
because malloc returns a pointer and every pointer is the base of an
array.

[toc] | [prev] | [next] | [standalone]


#142112

Fromscott@slp53.sl.home (Scott Lurndal)
Date2019-03-20 16:43 +0000
Message-ID<d5ukE.129284$%55.80346@fx40.iad>
In reply to#142106
nobody@example.org (Scott) writes:
>On Wed, 20 Mar 2019 04:40:25 GMT, Spiros Bousbouras <spibou@gmail.com>
>wrote:
>
>>But you don't get to do error checking either and if there isn't enough
>>memory to allocate the array , the programme will probably crash with an
>>uninformative error message.
>
>Well, maybe. On some contemporary operating systems, a malloc return
>value of non-null does not guarantee that the allocated memory
>actually exists. It can appear to succeed, and only explodes when you
>try to write to that phantom memory -- and there's no way to trap that
>fault in C.

Correction, no "standard C" method.   One may always catch SIGSEGV.

[toc] | [prev] | [next] | [standalone]


#142113

Fromfir <profesor.fir@gmail.com>
Date2019-03-20 10:00 -0700
Message-ID<ab52d075-4b69-42d5-8b2f-d0d4ed4bc107@googlegroups.com>
In reply to#142112
W dniu środa, 20 marca 2019 17:44:03 UTC+1 użytkownik Scott Lurndal napisał:
> nobody@example.org (Scott) writes:
> >On Wed, 20 Mar 2019 04:40:25 GMT, Spiros Bousbouras <spibou@gmail.com>
> >wrote:
> >
> >>But you don't get to do error checking either and if there isn't enough
> >>memory to allocate the array , the programme will probably crash with an
> >>uninformative error message.
> >
> >Well, maybe. On some contemporary operating systems, a malloc return
> >value of non-null does not guarantee that the allocated memory
> >actually exists. It can appear to succeed, and only explodes when you
> >try to write to that phantom memory -- and there's no way to trap that
> >fault in C.
> 
> Correction, no "standard C" method.   One may always catch SIGSEGV.

is there btw some method to obtail nore
infro from signal (like SIGSEGV) in c?
(specifically for example under winapi)

there is no much more irritating than 
haisenberg SIGSEGV ..i recently touched some of my not much important old code
(some simple irc client) and got random
SIGSEGV from there (sometimes present sometimes not, hell knows why and where

and as it was not much important to me i dropped searching for it... is there easy way?

[toc] | [prev] | [next] | [standalone]


#142145

FromWilliam Ahern <william@25thandClement.com>
Date2019-03-20 15:07 -0700
Message-ID<i5qamf-o71.ln1@wilbur.25thandClement.com>
In reply to#142112
Scott Lurndal <scott@slp53.sl.home> wrote:
> nobody@example.org (Scott) writes:
>>On Wed, 20 Mar 2019 04:40:25 GMT, Spiros Bousbouras <spibou@gmail.com>
>>wrote:
>>
>>>But you don't get to do error checking either and if there isn't enough
>>>memory to allocate the array , the programme will probably crash with an
>>>uninformative error message.
>>
>>Well, maybe. On some contemporary operating systems, a malloc return
>>value of non-null does not guarantee that the allocated memory
>>actually exists. It can appear to succeed, and only explodes when you
>>try to write to that phantom memory -- and there's no way to trap that
>>fault in C.
> 
> Correction, no "standard C" method.   One may always catch SIGSEGV.

On systems that overcommit memory (e.g. Linux, FreeBSD) a process is usually
killed with SIGKILL and it's not necessarily the process that triggered the
original fault.

Note that overcommit is distinct from unreserved allocations, e.g.
mmap+MAP_NORESERVE. The latter is documented to send SIGSEGV.

On Windows the nomenclature is slightly different: MAP_RESERVE doesn't
commit; one must use MAP_COMMIT in addition to MAP_RESERVE. But Windows
doesn't overcommit memory in the same manner as Linux. For one thing,
overcommit is a system-level option in Linux, beyond the control of a
process. In fact, as I recently had the unfortune to discover, even if you
theoretically mapped all your process memory to a backing store like a disk
file, which *should* guarantee availability, overcommit logic and heuristics
are so pervasive in the kernel that you can still get shot down, both when
triggering your own page fault or someone else triggering a page fault.

[toc] | [prev] | [next] | [standalone]


#142164

Fromfir is a sexy shemale <cdalten@gmail.com>
Date2019-03-20 23:52 -0700
Message-ID<9e3c2ce3-8274-4ab6-bc69-caa64638ee37@googlegroups.com>
In reply to#142145
I found something totally unawesome about arrays when used as a list. Sometimes if I don't treat them as a local variable, my system will allocate a heap size for the array itself instead of for the variables themselves.
This in turn leads to all kind of really fun bugs.

So instead of getting

[][][][extra byte]

I would get

[][][][] [extra byte][extra byte][extra byte][extra byte]

where the 4 extra bytes are viewed as a single unit by the operating system.


What is even better when I start having the array hold reference to another array. In which case the debugger can make the array buggy!

So what's the point of this incoherent babble? Just to picture an array as how it's discussed in academic textbook and not to add a creative interpretation of them.

[toc] | [prev] | [next] | [standalone]


#142185

Fromnobody@example.org (Scott)
Date2019-03-21 16:50 +0000
Message-ID<5c93be66.261340189@news.xmission.com>
In reply to#142112
On Wed, 20 Mar 2019 16:43:53 GMT, scott@slp53.sl.home (Scott Lurndal)
wrote:

>nobody@example.org (Scott) writes:
>>On Wed, 20 Mar 2019 04:40:25 GMT, Spiros Bousbouras <spibou@gmail.com>
>>wrote:
>>
>>>But you don't get to do error checking either and if there isn't enough
>>>memory to allocate the array , the programme will probably crash with an
>>>uninformative error message.
>>
>>Well, maybe. On some contemporary operating systems, a malloc return
>>value of non-null does not guarantee that the allocated memory
>>actually exists. It can appear to succeed, and only explodes when you
>>try to write to that phantom memory -- and there's no way to trap that
>>fault in C.
>
>Correction, no "standard C" method.   One may always catch SIGSEGV.

Agreed, one may do so, *if* the signal is sent. Seg fault happens when
you hit memory that isn't yours, but in the case of overcommit, the
page *is* yours, it just doesn't have any memory behind it. My
experiences here are brief and not conclusive at all, but when I wrote
a test program to really push the issue, the result was crashing the
entire OS more often than not, with no (catchable) signal ever sent to
my process.

Well, now I'm curious about what I'm forgetting. I'll see about
setting up a test box and re-run that experiment on a few different
OSes.

[toc] | [prev] | [next] | [standalone]


#142190

Fromscott@slp53.sl.home (Scott Lurndal)
Date2019-03-21 17:23 +0000
Message-ID<sMPkE.179115$KB3.56762@fx02.iad>
In reply to#142185
nobody@example.org (Scott) writes:
>On Wed, 20 Mar 2019 16:43:53 GMT, scott@slp53.sl.home (Scott Lurndal)
>wrote:
>
>>nobody@example.org (Scott) writes:
>>>On Wed, 20 Mar 2019 04:40:25 GMT, Spiros Bousbouras <spibou@gmail.com>
>>>wrote:
>>>
>>>>But you don't get to do error checking either and if there isn't enough
>>>>memory to allocate the array , the programme will probably crash with an
>>>>uninformative error message.
>>>
>>>Well, maybe. On some contemporary operating systems, a malloc return
>>>value of non-null does not guarantee that the allocated memory
>>>actually exists. It can appear to succeed, and only explodes when you
>>>try to write to that phantom memory -- and there's no way to trap that
>>>fault in C.
>>
>>Correction, no "standard C" method.   One may always catch SIGSEGV.
>
>Agreed, one may do so, *if* the signal is sent. Seg fault happens when
>you hit memory that isn't yours, but in the case of overcommit, the
>page *is* yours, it just doesn't have any memory behind it.

Some unix will send SIGBUS in this case, but most will send SIGSEGV.

> My
>experiences here are brief and not conclusive at all, but when I wrote
>a test program to really push the issue, the result was crashing the
>entire OS more often than not, with no (catchable) signal ever sent to
>my process.

You'd have to point out which OS.   The feature originated, IIRC, with
IBM's AIX in the 80's.

[toc] | [prev] | [next] | [standalone]


#142219

Fromnobody@example.org (Scott)
Date2019-03-22 04:29 +0000
Message-ID<5c945dc4.302138986@news.xmission.com>
In reply to#142190
On Thu, 21 Mar 2019 17:23:36 GMT, scott@slp53.sl.home (Scott Lurndal)
wrote:

>nobody@example.org (Scott) writes:
>>On Wed, 20 Mar 2019 16:43:53 GMT, scott@slp53.sl.home (Scott Lurndal)
>>wrote:
>>>Correction, no "standard C" method.   One may always catch SIGSEGV.
>>
>>Agreed, one may do so, *if* the signal is sent. Seg fault happens when
>>you hit memory that isn't yours, but in the case of overcommit, the
>>page *is* yours, it just doesn't have any memory behind it.
>
>Some unix will send SIGBUS in this case, but most will send SIGSEGV.
>
>> My
>>experiences here are brief and not conclusive at all, but when I wrote
>>a test program to really push the issue, the result was crashing the
>>entire OS more often than not, with no (catchable) signal ever sent to
>>my process.
>
>You'd have to point out which OS.   The feature originated, IIRC, with
>IBM's AIX in the 80's.

I previously checked on, IIRC, FreeBSD 8.4-R. I began re-running some
of my tests today on a fresh install of FreeBSD 12.0-R on an i5 PC
with 8Gb RAM and no swap. The test program is just a loop to allocate
a 1Gb block and memset it to a random value, repeatedly, until malloc
returns null or any signal is caught.

My results today were consistent over several runs. When memory was
exhausted, the system logged errors and began killing unrelated jobs,
ending with an uncrashed but unusable system. It was running, had a
login prompt, but logging in (even as root) just kicked you back to
the login prompt without comment. Notably, while my program was among
those killed, it never received a signal, and never got a null return
from malloc.

Curiously, 12.0 comes out of the box with overcommit disabled, and
with that I would expect malloc to eventually return null, but no.
I'll have to look harder to find out why. Probably there are kernel
tunables that need tweaking to prevent non-root jobs from doing that
much damage.

Tomorrow, time permitting, I'll repeat my tests with Ubuntu on the
same hardware, and I think another set of tests that more aggressively
harasses the overcommit mechanism. To be continued....

[toc] | [prev] | [next] | [standalone]


#142289 — OT: crashing malloc [was Re: heap memory indexed as an array]

Fromnobody@example.org (Scott)
Date2019-03-23 15:27 +0000
SubjectOT: crashing malloc [was Re: heap memory indexed as an array]
Message-ID<5c964dc4.429114439@news.xmission.com>
In reply to#142219
On Fri, 22 Mar 2019 04:29:43 GMT, nobody@example.org (Scott) wrote:
[Following up my own article, 'cause I'm classy that way]

>I previously checked on, IIRC, FreeBSD 8.4-R. I began re-running some
>of my tests today on a fresh install of FreeBSD 12.0-R on an i5 PC
>with 8Gb RAM and no swap. The test program is just a loop to allocate
>a 1Gb block and memset it to a random value, repeatedly, until malloc
>returns null or any signal is caught.
>
>My results today were consistent over several runs. When memory was
>exhausted, the system logged errors and began killing unrelated jobs,
>ending with an uncrashed but unusable system. It was running, had a
>login prompt, but logging in (even as root) just kicked you back to
>the login prompt without comment. Notably, while my program was among
>those killed, it never received a signal, and never got a null return
>from malloc.

Another round of testing, on Linux this time (Ubuntu Server 18.04),
produced similar results. Memory and swap exhausted, malloc never
returned null, and jobs killed with no signal received. But the OS did
not degenerate into a useless state this time. (That's a bit of an ego
blow, I've been a stout BSD weenie for years, but, meh.)

I guess I should test Windows next, and in fairness I should test it
natively instead of through cygwin. Another day though.

[toc] | [prev] | [next] | [standalone]


#142308

FromSpiros Bousbouras <spibou@gmail.com>
Date2019-03-23 19:24 +0000
Message-ID<EdfBdz5pbHcBscNMHR0FFjXOarp0b@bongo-ra.co>
In reply to#142219
On Fri, 22 Mar 2019 04:29:43 GMT
nobody@example.org (Scott) wrote:
> I previously checked on, IIRC, FreeBSD 8.4-R. I began re-running some
> of my tests today on a fresh install of FreeBSD 12.0-R on an i5 PC
> with 8Gb RAM and no swap. The test program is just a loop to allocate
> a 1Gb block and memset it to a random value, repeatedly, until malloc
> returns null or any signal is caught.
> 
> My results today were consistent over several runs. When memory was
> exhausted, the system logged errors and began killing unrelated jobs,
> ending with an uncrashed but unusable system. It was running, had a
> login prompt, but logging in (even as root) just kicked you back to
> the login prompt without comment. Notably, while my program was among
> those killed, it never received a signal, and never got a null return
> from malloc.

Such an outcome is serious enough that it would be worth mentioning on
some discussion forum specifically for FreeBSD.

> Curiously, 12.0 comes out of the box with overcommit disabled, and
> with that I would expect malloc to eventually return null, but no.
> I'll have to look harder to find out why. Probably there are kernel
> tunables that need tweaking to prevent non-root jobs from doing that
> much damage.

[toc] | [prev] | [next] | [standalone]


#142312

FromMelzzzzz <Melzzzzz@zzzzz.com>
Date2019-03-23 20:20 +0000
Message-ID<SxwlE.214327$Qp2.85363@fx11.am4>
In reply to#142308
On 2019-03-23, Spiros Bousbouras <spibou@gmail.com> wrote:
> On Fri, 22 Mar 2019 04:29:43 GMT
> nobody@example.org (Scott) wrote:
>> I previously checked on, IIRC, FreeBSD 8.4-R. I began re-running some
>> of my tests today on a fresh install of FreeBSD 12.0-R on an i5 PC
>> with 8Gb RAM and no swap. The test program is just a loop to allocate
>> a 1Gb block and memset it to a random value, repeatedly, until malloc
>> returns null or any signal is caught.
>> 
>> My results today were consistent over several runs. When memory was
>> exhausted, the system logged errors and began killing unrelated jobs,
>> ending with an uncrashed but unusable system. It was running, had a
>> login prompt, but logging in (even as root) just kicked you back to
>> the login prompt without comment. Notably, while my program was among
>> those killed, it never received a signal, and never got a null return
>> from malloc.
>
> Such an outcome is serious enough that it would be worth mentioning on
> some discussion forum specifically for FreeBSD.
>
>> Curiously, 12.0 comes out of the box with overcommit disabled, and
>> with that I would expect malloc to eventually return null, but no.
>> I'll have to look harder to find out why. Probably there are kernel
>> tunables that need tweaking to prevent non-root jobs from doing that
>> much damage.

Heh, Linux has more clever OOM killer ;)


-- 
press any key to continue or any other to quit...

[toc] | [prev] | [next] | [standalone]


#142221

FromTim Rentsch <tr.17687@z991.linuxsc.com>
Date2019-03-21 22:35 -0700
Message-ID<861s2zpj3k.fsf@mailhub.linuxsc.com>
In reply to#142086
Spiros Bousbouras <spibou@gmail.com> writes:

> On Tue, 19 Mar 2019 21:37:06 -0600
> Joe Pfeiffer <pfeiffer@cs.nmsu.edu> wrote:
>
>> sinbad <sinbad.sinbad@gmail.com> writes:
>>
>>> Is it safe to use heap memory as an array?
>>>
>>> #include <stdio.h>
>>> #include <string.h>
>>> #include <stdlib.h>
>>>
>>> typedef struct cell {
>>>     char name[5];
>>>     int y;
>>> } cell_t;
>>>
>>> #define MAX_CELLS 5
>>>
>>> int main() {
>>>     int i;
>>>     cell_t *p;
>>>
>>>     p = calloc(MAX_CELLS, sizeof(cell_t));
>
>     if (p == 0) return EXIT_FAILURE ;
>
>>>     for (i = 0; i < MAX_CELLS; i++) {
>>>         strcpy(p[i * sizeof(cell_t)].name, "test");
>>>         p[i * sizeof(cell_t)].y = i;
>>>     }
>>>
>>>     for (i = 0; i < MAX_CELLS; i++) {
>>>         printf("%s %u\n", p[i * sizeof(cell_t)].name,
>>>                p[i*sizeof(cell_t)].y);
>>>     }
>>>
>>>     free(p);
>>>     return 0;
>>>
>>> }
>>
>> Not only is it OK to use dynamically allocated memory with an index
>> ("like an array"), it's easier than your code indicates.
>>
>> You don't need to multiply the index by the cell size -- the compiler
>> does that for you.
>>
>>          printf("%s %u\n", p[i].name,
>>
>> will work in your printf().
>
> That depends on what the full  printf() invocation says.  The obvious
> extrapolation from the original code would be
>     printf("%s %u\n", p[i].name, p[i].y) ;
>
> but this is undefined behaviour because  p[i].y  has type  int  whereas
> %u  is for  unsigned int.

In fact the behavior is defined in this case, because the p[i].y
values are all small and non-negative.  The rules for variadic
arguments say it's okay to pass int for unsigned int, and vice
versa, as long as the value is in the common set of values for
the two types.  (The same applies to long and unsigned long,
etc.)  As a matter of style having the format specification match
the actual type is better of course, but the behavior in this
particular case is well-defined despite the signed/unsigned
mixing.

[toc] | [prev] | [next] | [standalone]


#142094

FromJorgen Grahn <grahn+nntp@snipabacken.se>
Date2019-03-20 07:05 +0000
Message-ID<slrnq93pgt.4jo.grahn+nntp@frailea.sa.invalid>
In reply to#142084
On Wed, 2019-03-20, sinbad wrote:
> Hi,
>
> Is it safe to use heap memory as an array?

Don't think of it as using heap memory "as an array"; think about it
as allocating an object (a struct, an array, a struct containing an
array, or something different) on the heap.  Then you use that object,
not the underlying memory.

/Jorgen

-- 
  // Jorgen Grahn <grahn@  Oo  o.   .     .
\X/     snipabacken.se>   O  o   .

[toc] | [prev] | [next] | [standalone]


#142102

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2019-03-20 12:12 +0000
Message-ID<87sgvhzqvd.fsf@bsb.me.uk>
In reply to#142084
sinbad <sinbad.sinbad@gmail.com> writes:

> #include <stdio.h>
> #include <string.h>
> #include <stdlib.h>
>
> typedef struct cell {
>     char name[5];
>     int y;
> } cell_t;
>
> #define MAX_CELLS 5
>
> int main() {
>     int i;
>     cell_t *p;
>
>     p = calloc(MAX_CELLS, sizeof(cell_t));
>
>     for (i = 0; i < MAX_CELLS; i++) {
>         strcpy(p[i * sizeof(cell_t)].name, "test");
>         p[i * sizeof(cell_t)].y = i;
>     }
>
>     for (i = 0; i < MAX_CELLS; i++) {
>         printf("%s %u\n", p[i * sizeof(cell_t)].name,
>                p[i*sizeof(cell_t)].y);
>     }
>
>     free(p);
>     return 0;
>
> }

Here's another way to write this program with about half a dozen
changes, some of which you (or others) may find interesting:

#include <stdio.h>
#include <stdlib.h>

typedef struct cell {
    char name[5];
    int y;
} cell_t;

#define MAX_CELLS 5

int main(void)
{
     cell_t *p = malloc(MAX_CELLS * sizeof *p);

     for (int i = 0; i < MAX_CELLS; i++)
          p[i] = (cell_t){"test", i};

     for (int i = 0; i < MAX_CELLS; i++)
          printf("%s %d\n", p[i].name, p[i].y);

     free(p);
}

-- 
Ben.

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.c


csiph-web