-1

This program I'm working on with another person was running fine at some point. Then sometimes it would crash but then run fine again after restarting Windows. Was very intermittent and now always crashes. At some point I thought maybe its because I upgraded to Windows 10 somehow (I know). On my Windows 10 machine it now it always crashes no matter what.

So I installed VS on my Windows 7 machine and got different behavior again.

So it runs fine but displays no output if it is run without debugging.

If I run with debugging it triggers an unhandled exception break point when allocating memory in the following section of code.

/*
* clone()
* Precondition: s is defined and not NULL
* Postcondition: a copy of s has been returned
* Informally: Clone a sample
*/

sample clone(sample s)
{
    sample c;

    c = (sample)malloc(sizeof(struct sample_int)); //<-----exception error

    c->name = (char *)malloc((strlen(s->name) + 1)*sizeof(char));
    strcpy(c->name, s->name);

    c->sequence = (char *)malloc((strlen(s->sequence) + 1)*sizeof(char));
    strcpy(c->sequence, s->sequence);

    c->match = s->match;

    return c;
}

When clicking continue I get an Access Violation at location... error.

By this stage it is the 2nd time the function has been called. Below is the header file for sample.c

/*
 * Specification for the Sample ADT
 * Author Julian Dermoudy
 * Version 20/8/15
 */

#ifndef SAMPLE_H
#define SAMPLE_H

struct sample_int;
typedef struct sample_int *sample;

void init_sample(sample *s, char *name, char *sequence);
char *getName(sample s);
char *getSequence(sample s);
int getMatch(sample s);
void setName(sample s, char *name);
void setSequence(sample s, char *name);
void setMatch(sample s, int m);
sample clone(sample s);
char *toString(sample s);

#endif

The clone function is taking an existing sample struct with data in all fields.

Am I missing something about malloc? And why would it seem to work fine on one computer never on another and bring up this exception error on yet another computer?

Any advice would be greatly appreciated.

Brad
  • 741
  • 7
  • 17
  • 1
    You error is most likely not in that section of code. You probably wrote past the bounds of a memory buffer or double-free'ed a pointer someplace else. A memory checking tool like the ones mentioned [here](http://stackoverflow.com/questions/413477/is-there-a-good-valgrind-substitute-for-windows) should help you find where the error is. – dbush Sep 15 '15 at 15:39
  • 5
    What does the compiler do when you remove the casts of `malloc()` return value? – Weather Vane Sep 15 '15 at 15:41
  • 1
    In particular, you can't assign a `sample c` from `malloc()` ... you have to assign it to a `sample *c`. – TripeHound Sep 15 '15 at 15:48
  • 1
    You _shouldn't_ [cast the result of malloc](http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc?rq=1). – Enzo Ferber Sep 15 '15 at 15:48
  • 2
    @TripeHound `sample` is defined as `typedef struct sample_int *sample`. It's a pointer. – Enzo Ferber Sep 15 '15 at 15:49
  • 1
    `struct sample_int;` does not provide enough information for `sizeof(struct sample_int)` – Weather Vane Sep 15 '15 at 15:51
  • Where is your `struct sample_int` defined? Do you include that? – Enzo Ferber Sep 15 '15 at 15:53
  • @WeatherVane: if struct sample_int was not defined, if should raise a compile error not a run time one. – Serge Ballesta Sep 15 '15 at 16:03
  • @EnzoFerber Missed the defn. in the second code snippet. Bad type name as well as unnecessary cast. – TripeHound Sep 15 '15 at 16:04
  • 1
    As to why you observe different behavior on different machines, that you do so is a strong indication that some aspect of your program's behavior is in fact *undefined* by the language semantics. In that case, you cannot rely on anything about the program's behavior -- including whether it fails at all. – John Bollinger Sep 15 '15 at 16:07
  • 1
    Go with dbush's comment -- the problem is *most definitely* somewhere else. Still, adding to the advice already given, I'd also suggest not to hide a pointer *type modifier* behind a `typedef`. Rationale: this looks confusing, most other C programmers will first think it's not a pointer at all. –  Sep 15 '15 at 16:10
  • In practice, it sounds like you have an out-of-bounds memory access and/or a dereference of an invalid pointer value. Perhaps you have that only in a subset of cases. It doesn't look like your `clone()` function is the locus of the problem, though if passed bad data it could serve as the trigger. – John Bollinger Sep 15 '15 at 16:11
  • ...and return value `NULL` from `malloc` will cause grief... not checked. – Weather Vane Sep 15 '15 at 16:12
  • All in all, suggested C style for type definition: `typedef struct sample sample;` and for allocation: `sample *s = malloc(sizeof(sample));` <- clean and simple –  Sep 15 '15 at 16:12
  • 4
    If it is now *always* crashing, then it should be easy for you to prepare a [minimal complete example](http://stackoverflow.com/help/mcve). 1) This is a vital skill, 2) you'll probably uncover the bug yourself while whittling the code down, 3) it'll make our job much easier, which means that 4) more of us will try, and anyway 5) I don't think we have a chance without it. – Beta Sep 15 '15 at 16:13
  • 4
    Or `sample *s = malloc (sizeof *s);` – David C. Rankin Sep 15 '15 at 16:15
  • its only ALWAYS crashing on 1 computer. Works fine on another and returns exception fault on the 3rd. – Brad Sep 15 '15 at 16:29
  • So i think there's a problem because the struct contains an int. Everything else inside it is a pointer but match is a direct int. For some reason if I don't try and assign anything to match everything runs fine. Any Ideas? – Brad Sep 15 '15 at 21:22
  • It looks like the write to (*s)->match clobbers some structure that is used by the heap management. In cases like this it usually helps to wrap malloc and friends into helper functions that allocate a bit more memory and put some guard bytes at the front and end of your allocations (returning a pointer to the memory after the initial guard bytes) and add a function that checks your malloced memory blocks before you do something with them. In this way you can edge your way closer to where your memory corruption problem actually happens. – Markus Dheus Sep 23 '15 at 13:18
  • Read [*How to debug small programs*](https://ericlippert.com/2014/03/05/how-to-debug-small-programs/) then use [valgrind](http://valgrind.org) – Basile Starynkevitch Aug 11 '19 at 07:08

1 Answers1

1

Just wanting to answer this old question from long ago when I was a noob with no rep to answer. (originally answered it with an update to the question).

Somewhere else in the code I was allocating memory the size of a pointer to a struct. I'm guessing this causes tiny excess or misalignment in memory allocation.

Not exactly sure why but this causes the very next use of malloc to crash but only under certain environmental conditions.

The crashing happening long after the problem code was executed caused me to look for the problem in all the wrong places. Eventually I sat down and rewrote the entire program until eventually I noticed one line of code was allocating sizeof(a pointer).‍♂️

So allocating sizeof(the actual struct) rather than sizeof(pointer to the stuct) fixed all the problems.

Brad
  • 741
  • 7
  • 17
  • 1
    (a) You could think about removing the answer from the question. (b) You should think about the advice in [Is it a good idea to typedef pointers](https://stackoverflow.com/questions/750178/) — TL;DR the answer is generally "No". – Jonathan Leffler Aug 11 '19 at 06:35