Как я могу скомпилировать и запустить эту написанную в 1989 году программу на C?

Я нашел удивительную работу Артура Уитни — http://www.jsoftware.com/jwiki/Essays/Incunabulum

Он скомпилирован с несколькими предупреждениями

$ gcc-4.7 incuna.c -o incuna.o
incuna.c: In function 'ma':
incuna.c:8:15: warning: incompatible implicit declaration of built-in function 'malloc' [enabled by default]
incuna.c: In function 'pi':
incuna.c:26:7: warning: incompatible implicit declaration of built-in function 'printf' [enabled by default]
incuna.c: In function 'nl':
incuna.c:26:24: warning: incompatible implicit declaration of built-in function 'printf' [enabled by default]
incuna.c: In function 'pr':
incuna.c:28:10: warning: incompatible implicit declaration of built-in function 'printf' [enabled by default]
incuna.c: In function 'ex':
incuna.c:35:36: warning: assignment makes integer from pointer without a cast [enabled by default]
incuna.c:35:25: warning: return makes pointer from integer without a cast [enabled by default]
incuna.c: In function 'noun':
incuna.c:37:57: warning: return makes integer from pointer without a cast [enabled by default]
incuna.c: In function 'wd':
incuna.c:39:21: warning: incompatible implicit declaration of built-in function 'strlen' [enabled by default]

Но произошел сбой при вводе основного ввода 1 + 1.

./incuna.o
warning: this program uses gets(), which is unsafe.
1 + 1
[1]    11525 segmentation fault  ./incuna.o

Я предполагаю, что это как-то связано с разницей в компиляторе C с 1989 года.

Как я смогу запустить это? Могу ли я заставить это работать на последних версиях Linux/Mac? или на виртуальной машине VirtualBox? или что-нибудь еще?

Мои поиски в Google ничего не дали.


person user1527166    schedule 11.12.2012    source источник
comment
Возможно, вы могли бы попробовать запустить программу в gdb, чтобы увидеть больше информации?   -  person SSH This    schedule 11.12.2012
comment
#include <stdio.h> возможно? Изменить: исправлен синтаксис   -  person leppie    schedule 11.12.2012
comment
Это похоже на переполнение буфера из-за gets()   -  person Zaffy    schedule 11.12.2012
comment
1+1 не segfault. Просто думал, что вы должны знать.   -  person Daniel Kamil Kozar    schedule 11.12.2012
comment
@leppie, добавил, тот же результат.   -  person user1527166    schedule 11.12.2012
comment
@DanielKamilKozar, странно. 1+1 делает segfault для меня.   -  person user1527166    schedule 11.12.2012
comment
@ user1527166 - Посмотрите на мой обновленный ответ, у вас неправильный интервал. В своем вопросе вы сказали 1 + 1, чтобы выделить ошибку, вам нужно ввести 1 + 1 (без пробелов)   -  person Mike    schedule 11.12.2012
comment
Нашел эту страницу с некоторым объяснением кода: jsoftware.com/papers/AIOJ/AIOJ. htm   -  person luser droog    schedule 29.03.2013
comment
Дополнительные пояснения: groups.google.com/d/msg/sayeret-lambda. /Oxffk3aeUP4/QEuZocgVh5UJ   -  person luser droog    schedule 29.03.2013
comment
Дополнительные пояснения: archive.vector.org.uk/trad/v094/hui094_85.pdf‎ [pdf, отсканированный из журнала]   -  person luser droog    schedule 07.03.2014


Ответы (4)


Он преобразует указатели в int и long и наоборот. Это не работает с 64-битными архитектурами, в которых они имеют разные размеры.

Скомпилируйте его для 32-битной цели. Например, с «-arch i386» с использованием clang/LLVM в Mac OS X.

person Eric Postpischil    schedule 11.12.2012
comment
Или -m32 для gcc. Это может быть отличным примером программы, которая не является 64-битной. ;) - person Daniel Kamil Kozar; 11.12.2012

Могу поспорить, что это произошло из-за этого:

incuna.c:8:15: предупреждение: несовместимое неявное объявление встроенной функции 'malloc' [включено по умолчанию]

Если malloc не объявлен, то он не будет выделять вам память, и в конечном итоге вы разыменуете нулевое значение, что может привести к ошибке seg.

После включения:

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

Предупреждения для printf(), malloc() и strlen() исчезли. Код запускается и работает, если вы вводите:

1+1

Обратите внимание, что здесь важен интервал:

1 + 1 

будет segfault.

person Mike    schedule 11.12.2012
comment
Вероятно, вы забыли включить ‹stdlib.h›. - person SSH This; 11.12.2012
comment
@SSHThis, включая stdlib, удалило предупреждение, но segfault остается. - person user1527166; 11.12.2012
comment
Замечательно! Это и приведенный ниже ответ Эрика об использовании i386 arch работали в моей 64-битной среде :) - person user1527166; 11.12.2012
comment
Добавьте #include <string.h>, чтобы предоставить объявление и для strlen(). - person Jonathan Leffler; 11.12.2012
comment
@JonathanLeffler - Хороший вопрос, я не включил -Wall, поэтому я пропустил это там. Обновлено - person Mike; 11.12.2012
comment
отсутствие объявления malloc() не приведет к тому, что он вернет ноль и каким-то образом не сможет выделить память! Если программа по-прежнему правильно связывается, то malloc() все еще существует и вызывается, хотя, как указано в правильном ответе, возвращаемое значение может быть обработано неправильно, если указатель и int имеют разные размеры. - person Greg A. Woods; 12.12.2012

Запустите его только через препроцессор:

gcc -E интерп.с > интерп-пп.с

Затем украсьте его в редакторе, затем используйте отладчик, чтобы посмотреть, что он делает.

person paul tarvydas    schedule 11.12.2012

В моей системе (AMD64 Win 8) кажется, что значения указателя часто имеют установленный верхний бит, поэтому обработка указателя как целого числа (что делает эта программа) приведет к неправильному поведению и сбою.

Изменение функции qv(a) ("глагол запроса") позволяет программе работать:

qv(a){R a<'a';}

должно быть

qv(a){R a<'a'&&a>0;}

or

qv(a)unsigned a;{R a<'a';}

Вот ссылка на минимально модифицированную версию, которая должна компилироваться без предупреждений (с gcc , параметры по умолчанию) и выполнить (с правильным вводом).

person luser droog    schedule 18.03.2014
comment
Я создал проект на github, расширяющий эту причудливую маленькую программу. ссылка - person luser droog; 28.03.2014