Hacker News new | ask | show | jobs
by canucker2016 12 days ago
You just had to live with the constraints.

It biased your selection of data structures and algorithms.

Max 64KB array size meant pointers to allocated structs and linked lists were much more popular back then versus 1 large array of structs.

The Win16 HANDLE memory allocation also meant you had to worry about how you handle structs which had pointers to others structs (a FAR ptr may not be a stable value, unless you locked the HANDLE for the duration of the allocation)

Then you had to worry about stuff that no college programming book talked about (ignore the lack of error checking):

  char FAR *p;
  char FAR *mem = farmalloc(65536);

  for (p = &mem[65535]; p >= &mem[0]; p--) {
    dostuff(p);
  }
Welcome to an infinite loop...
1 comments

  char FAR *p;
  char FAR *mem = farmalloc(65536);

  for (p = &mem[65535]; p >= &mem[0]; p--) {
    dostuff(p);
  }
Nice one.

To be fair to Windows, good C courses should still teach this, but I'm not sure if they do :-)

It's UB to set a pointer to before the first element of an array, or after the last element plus one. So, if it knows the call to farmalloc/malloc returns the start of an object, a modern C compiler on a modern architecture may, in principle, optimise the above to an infinite loop.

I've seen something similar on architectures (long ago) where a zero-bit-pattern pointer was a valid memory address you might actually access. Of course p-1 is not less than p when p is zero.

None of my college CS courses used programming languages that featured FAR pointers.

The above example would cause an infinite loop on Win16's seg:off far memory model, but compiling on Win32 would not cause an infinite loop.

Problem is that far pointers only affect the offset, not the segment. So decrementing a 0 value offset would just wrap around to 0xFFFF and the segment would stay the same, so you're going from mem[0] to mem[65535] not mem[-1].

My point is the example code has a generic C bug, not depending on FAR, which is why it should be taught in good C courses.

Although the code worked on Win32, and works on most modern C compilers, it's not guaranteed to work on modern C compilers, especially with aggressive optimisation turned on.

I'm not disputing your point.

I'm explaining why the infinite loop actually occurs for those who haven't encountered the problem.

The problem would happen for an array whose beginning element starts at offset 0 for a particular segment and an iteration stop condition that uses ">= 0th element" that scans down the array. I used a 64K allocated array to ensure that the array base would match offset 0.

Problem would also occur if the end of the array aligns with the segment limit and the iteration end condition was "<= end element" and the scan moves up the array.

For either situation, the array could be < 64KB. One byte would be sufficient.