overwriting memory

Discussion in 'C Programming' started by Robbie Brown, Jan 26, 2014.

  1. Robbie Brown

    Robbie Brown Guest

    You're very kind :)

    Anyway, I'm pretty sure I see what you mean, I'll do some experimenting
    tomorrow, it's been a long day.

    BTW valgrind is a wicked bit of kit, cheers for the heads up.

    I was convinced my dynamically allocated LinkedList was working, and it
    was but I hadn't got the freeing up of memory quite right, there was a
    small leak that I was able to fix and an unitialized variable that I
    hadn't caught. I would *never* have figured that out at my current level
    of knowledge without.
    Robbie Brown, Jan 26, 2014
    1. Advertisements

  2. If var is a type, then the type "pointer to var" would be var*, not
    *var. For example, sizeof (int*) is the size of a pointer to an int.
    (And I hope you wouldn't name a type "var".)

    To be a bit more explicit about the syntax, there are two forms of
    the sizeof operator. One takes an expression as an operand:

    sizeof expr

    The other takes a parenthesized type name:

    sizeof (type-name)

    The expression can of course be a parenthesized expression, and there
    are cases where it needs to be just for grouping, but in general
    parentheses aren't needed unless the argument is a type name. (And in
    most cases, you *want* an expression rather than a type name.)

    Keith Thompson, Jan 27, 2014
    1. Advertisements

  3. Among other things, you seem to be assuming that an int is 32 bits and a
    pointer is 64 bits. That may happen to be the case on the system you're
    using, but it's not specified by the language. int can legally be as
    narrow as 16 bits; 32 bits happens to be typical these days. Pointers
    are typically either 32 or 64 bits, though other sizes are possible.

    The language doesn't even guarantee that all pointer types have the same
    size; for example, void* might be bigger than int*.
    Keith Thompson, Jan 27, 2014
  4. Robbie Brown

    JohnF Guest

    Wow, you're channeling (in the medium/spirit_guide sense)
    my old contract
    which was actually on my mind when I posted the malloc/calloc
    followup here.
    Had to write various binomial tree algorithms, and wrote
    a library to encapsulate the low-level operations.
    Considered your method above for allocation (double *talloc(n)
    allocates a tree with n periods), but instead used the fact
    that the triangle contains n*(n+1)/2 nodes and calloc'ed them
    all at once. Indexing tree[period,node], node=0...period-1, then
    done by #define tindex(period,node) ((period*(period+1)/2)+node)
    so you'd write tree=talloc() and address tree[tindex()].
    Your alternative certainly demonstrates current topic better,
    but the other actually executed a bit faster on DECstation 5000
    (based on MIPS 3000 chipset), though I don't know (and didn't
    really try to find out) exactly why.
    The reason it was on my mind when posting is that original
    code, from 1991, ran and produced identical results at that time,
    on DECstation 5000, Apollo 10000, a pretty fast VAX but I can't
    recall which, and a PC running DOS with the Zortech C compiler.
    But when I tried to get it running a year or two ago under linux,
    got nan's all along the "edges" (nodes representing maximum
    volatility), but okay numbers elsewheres. Must be something
    that got initialized way back when (since it worked and was
    checked incredibly thoroughly), and isn't initialized now.
    But I couldn't track it down. Fortunately, no money was involved.
    Just a free little online calculator I was going to write, advising
    people when to refinance their mortgages (a friend was making
    that decision, but not understanding how to properly go about it).
    So anyway, I did a double- and triple-take when you
    suggested that example. Seemed like you were reading my mind.
    And just to check: I'm thinking of a number from 1 to 10...
    Thanks for additional info and examples.
    JohnF, Jan 27, 2014
  5. Robbie Brown

    JohnF Guest

    Unnecessary. I almost always over-cast, maybe an artifact of
    memories of Fortran II mixed-mode errors.

    As above, just unnecessary.
    I think I'd stick with sizeof(Type) for very simple allocations
    like the double *array=malloc(n*sizeof(double)); example.
    Just seems more readable to me, and not particularly more
    error-prone than anything else. But for allocating complicated
    typedef's, or such, I agree maybe your/Ben's way is better.
    Well, the discussion's convincing, but not really the above
    example, where it seems to me that I could just have easily
    blundered by writing MessagePayload *msg = malloc(sizeof *hdr); //?
    JohnF, Jan 27, 2014
  6. Robbie Brown

    Robbie Brown Guest

    Well you have to start somewhere don't you? On this machine, as I have
    observed, addresses are reserved in 64 bits and ints 32. Well actually
    even this appears to be incorrect. I have never seen an address that
    appears larger than 48 bits ... starting with 7f so a 48 bit signed
    integer which is ... er, lots of memory. I was going to say 'obviously'
    next but I've learned that obvious is not a word I feel qualified to use
    when discussing C, oh what the hell, obviously (I think) the reason that
    addresses are stored in 64 bits is because that is the width of the data
    bus so 48 bits are address and 16 bits are padding. Like I say, you have
    to start somewhere. If I discover I'm wrong then I've learned something.
    I don't understand this at all. An address is an address is an address
    .... isn't it?.
    Robbie Brown, Jan 27, 2014
  7. Robbie Brown

    Seebs Guest

    "Bits that are always zero" is not the same thing as "not part of the
    object". It's most likely that the addresses are actually 64-bit, but that
    nothing on this particular machine happens to have an address in some part
    of that range.
    Not necessarily. Machines have existed where you might have more bits in
    a pointer to a character than in a pointer to an int. There's lots of
    interesting variance out there.

    Seebs, Jan 27, 2014
  8. Robbie Brown

    James Kuyper Guest

    Yes, but the best place to start, as far as this particular issue is
    concerned, is with the understanding that you don't know for certain
    what the size of anything is, except insofar as your code uses sizeof to
    find out. The result that sizeof gives is only guaranteed correct for
    that particular implementation of C - it might be different on a
    different implementation. Later on, you can learn that there are some
    things you can be certain of about the sizes of various types, but the
    best place to start is acknowledged ignorance, not system-specific
    unjustified certainty.

    The standard example of how this can come about is word-addressed
    systems where the word is bigger than one byte. Pointers to word-aligned
    types need only contain the address of the word where the object starts.
    Pointers to types with alignment requirements that are smaller than a
    word must contain both the address of a word, and an offset within the
    word. Depending upon the word size and the amount of memory that needs
    to be addressed, storing that extra information might require that such
    pointers be larger than the word-aligned ones.
    There may be other reasons why pointers to different types might have
    different sizes, though I've never heard of one.

    All that the C standard has to say about this is that pointers to
    incompatible types are themselves incompatible types; you should avoid
    writing code that assumes that any two such pointer types have the same
    size, representation, or alignment requirement. Exception: void* is
    guaranteed to have the same representation and alignment requirements as
    pointers to char, signed char, and unsigned char.
    James Kuyper, Jan 27, 2014
  9. Robbie Brown

    James Kuyper Guest

    The compiler will give you an error _message_. The error itself was
    already there, having been introduced by your use of that macro. And
    there would not have been an error to report if it had instead been written
    int *i = malloc(sizeof *i);
    James Kuyper, Jan 27, 2014
  10. Robbie Brown

    James Kuyper Guest

    That's an example of what I was referring to when I wrote, in the
    section you snipped, that "Later on, you can learn that there are some
    things you can be certain of about the sizes of various types ..."
    James Kuyper, Jan 27, 2014
  11. Robbie Brown

    Robbie Brown Guest

    Who's Mr Spoons
    Why is it ridiculous?
    Robbie Brown, Jan 27, 2014
  12. Google (and IMDB) is (are) your friend(s).
    It's subtle, but if you stick around CLC long enough to absorb the, er,
    shall we say, "unique" culture around here, you'll get it.
    See above. It's hard to explain, but you'll get it in time.
    Suffice to say that rgrdev is definitely someone to follow. He's got the
    pulse on this group down to a T.

    Windows 95 n. (Win-doze): A 32 bit extension to a 16 bit user interface for
    an 8 bit operating system based on a 4 bit architecture from a 2 bit company
    that can't stand 1 bit of competition.

    Modern day upgrade --> Windows XP Professional x64: Windows is now a 64 bit
    tweak of a 32 bit extension to a 16 bit user interface for an 8 bit
    operating system based on a 4 bit architecture from a 2 bit company that
    can't stand 1 bit of competition.
    Kenny McCormack, Jan 27, 2014
  13. Please don't feed the troll.
    Keith Thompson, Jan 27, 2014
  14. Robbie Brown

    James Kuyper Guest

    I'm not sure he's seen enough of Richard's messages yet to justify
    concluding that Richard is a troll. If he hasn't, it's premature to
    criticize him for "feeding the troll". You could just tell Robbie that
    "Richard is a troll, ignore him", but I think it's best to just let him
    figure that out for himself.
    James Kuyper, Jan 27, 2014
  15. It was intended as advice, not as criticism. I more or less assumed
    that all that was implicit in what I wrote. But yes, it's likely
    I was insufficiently clear, and your addendum is helpful.

    Robbie: Richard is a troll; I suggest ignoring him.
    Keith Thompson, Jan 27, 2014
  16. Robbie Brown

    Jorgen Grahn Guest

    To be precise, /one/ of them is. There are two in the thread.

    Jorgen Grahn, Jan 29, 2014
  17. Robbie Brown

    Jorgen Grahn Guest

    It might be, but speaking as a C++ user I wouldn't use it. Most of the
    interesting features of C++ 'new' are absent, so it would just confuse

    Jorgen Grahn, Jan 29, 2014
  18. Right, I'm referring to the Richard who posts without a last name (his
    e-mail address is something like ), not (at all!) to
    Richard Damon.
    Keith Thompson, Jan 29, 2014
  19. Robbie Brown

    James Kuyper Guest

    There was only one that was directly relevant, having been quoted
    earlier. Richard uses only a mononym as identification, - perhaps he's
    Javanese? :) When it's less clear than it is in this case, people
    sometimes refer to him using some variant on "Richard NoName".
    James Kuyper, Jan 29, 2014
  20. Yes, it's highly confusing to use a C++ keyword in upper case, particularly
    if you're stripping functionality out.
    What I often to however is have a structure name in all-caps, and a
    constructor for it using the same name, in lower case. So it looks rather
    like a C++ call. Of course you initialise all the fields in the function.
    Malcolm McLean, Jan 29, 2014
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.