- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
enum {
HOST = INADDR_LOOPBACK,
PORT = 6666,
MAX_BUF = 1024
};
struct sock {
int sockfd;
int addrlen;
struct sockaddr_in addr;
} host, client;
int check(int x, char*msg)
{
if (!~x) {
perror(msg);
exit(1);
}
return x;
}
#define QUOTE_(...) #__VA_ARGS__
#define QUOTE(...) QUOTE_(__VA_ARGS__)
#define CHECK(...) check(__VA_ARGS__, QUOTE(line __LINE__: __VA_ARGS__))
int main(int argc, char**argv)
{
struct sock host, client;
host.sockfd = CHECK(socket(AF_INET, SOCK_STREAM, 0)),
host.addr = (struct sockaddr_in){AF_INET, htons(PORT), htonl(HOST)};
CHECK(bind(host.sockfd, &(struct sockaddr)host.addr, sizeof(host.addr)));
CHECK(listen(host.sockfd, 1));
CHECK(client.sockfd = accept(host.sockfd, (void*)&client.addr, &client.addrlen));
printf("connected: %s\n", inet_ntoa(client.addr.sin_addr));
struct {int len; char buf[MAX_BUF];} msg;
while (CHECK(msg.len = recv(client.sockfd, msg.buf, MAX_BUF - 1, 0)) && msg.len) {
msg.buf[msg.len] = 0;
printf("%s", msg.buf);
send(client.sockfd, msg.buf, msg.len, 0);
}
close(client.sockfd);
close(host.sockfd);
return 0;
}
Почему если закоментить 36-ю строчку адрес килента 0.0.0.0?
Переменные с теми же самыми именами объявлены в функции main (что обычно кладётся в стек):
Если убрать локальное объявление (ту самую 36-ю строку), то у нидлеса программа не может определить адрес клиента.
И правильно делает! Ибо accept'у некуда писать этот адрес. В отличие от случая с локалкой где всё случайно работает из-за UB'а.
В глобалке - ноль. В локалке - UB.
Инициализируйте переменные, блеать.
The addrlen argument is a value-result argument: the caller must initialize it to contain the size (in bytes) of the structure pointed to by addr; on return it will contain the actual size of the peer address.
The returned address is truncated if the buffer provided is too small; in this case, addrlen will return a value greater than was supplied to the call.
Х.з., сомнительный ворнинг так то (у студии есть, емнип). Из хедеров много всякого говна торчит, которое ты никогда юзать не будешь. Запрещать все эти имена юзать в качестве локалок, имхо, оверкилл.
А вот в пределах одной функции можно было бы и показать, это на 99% залёт. Но тоже нет.
В обоих случаях результат зависит от деталей реализации.
1. Глобальные переменные.
У секции .data есть инициализированная часть, лежащая в экзешнике, которая забита нулями и прочими начальными значениями (константами и правой частью от выражений типа int x = 42;), и неинициализированная часть, которая создаётся после загрузки (чем она забита, решает загрузчик экзешника).
Кудкудкудкуда ляжет переменная (в инициализированную часть или в неинициализированную), решают кококонпелятор и линкер.
2. Локальные переменные.
Тут всё хуже. В стек может наложить кто угодно. Я помню, как Царь полагался на то, что его промежуточные данные в стеке между вызовами функций сохраняются, и его программа обломалась в Ideone, где какой-то патч типа Propolice или Stackguard чистит стек вилкой.
Значит, у Нидлеса вариант с локальными переменными работает только потому, что по счастливой случайности кто-то в эту область стека положил ненулевые значения.
6.7.8 Initialization
10) <...> If an object that has static storage duration is not initialized explicitly, then <...> if it has arithmetic type, it is initialized to (positive or unsigned) zero.
А с «неарифметическими» что будет?
- if it has arithmetic type, it is initialized to (positive or unsigned) zero;
- if it is an aggregate, every member is initialized (recursively) according to these rules;
- if it is a union, the first named member is initialized (recursively) according to these rules.
Но это всё касается только static storage duration, на локалки это правило не действует и они наполнены UB'ами.
А если другие члены окажутся длиннее первого, то их хвосты можно не инициализировать?
> если операционка не справляется
Ну это странно... У процесса своей грязной памяти ещё нету, а брать её из других процессов не почистив вилкой - ебучее решето. Хотя какая-нибудь мелкая ось, у которой всё доверенное и без изоляции, в принципе, имеет право.
Накладок не будет т.к. только первый именованный из них обязан инициализироваться.
> использовать не 754
Походу да:
Annex F (normative) IEC 60559 floating-point arithmetic
F.1 Introduction
1) <...> An implementation that defines __STDC_IEC_559__ shall conform to the specifications in this annex.
Другим плавучим питухам просто нельзя объявлять это макро.
1. MBF (Microsoft binary format, BASIC). Порядок со смещением 128, причём для чисел любой точности. Старший разряд мантиссы подразумевается равным единице, как у IEEE 754. Denormal, inf, NaN не поддерживаются. Знаковый бит где-то в середине.
Если все биты обнулены, то хранится +0.
2. HFP (hexadecimal floating point, IBM System/360). Порядок со смещением 64 для чисел любой точности, основание порядка равно 16, а не 2 (поэтому старший подразумеваемый разряд мантиссы равен нулю). Знаковый бит в самом начале.
Если все биты обнулены, то хранится +0.
3. 48-битный Real в Трубопаскакале. Порядок хранится со смещением 128. Мантисса записывается задом наперёд. Знаковый бит где-то в середине. Старший разряд мантиссы подразумевается равным единице, как у IEEE 754.
Если все биты обнулены, то хранится +0.
Найденные питухи легко обнулять. Нужно найти какой-нибудь посложнее.
У БЭСМ порядок хранился без смещения (т. е. нули соответствовали не минимальному значению, а нулевой степени). Но я пока ещё не прочитал, как там хранилась мантисса.
В любом случае, у БЭСМ-6 ноль состоял из нулей. А вот минус нуля (судя по дополнительному коду) не было.
P.S. Какие ещё плавпитухи бывают?
P.P.S. В IEEE 754 описан ещё двоично-десятичный питух. Строится он по тому же принципу, что и двоичный, только бывают ненормальные кодировки порядка для экономии битов.
6.2.5 Types
18) Integer and floating types are collectively called arithmetic types.
Или её ещё нет или вообще нет, а сишку юзать хочется...
всмысле некуда? Я же передал укозатель на сьруктуру?
З.Ы. Первый вопрос, который должен возникать при вызове незнакомой функции - "а где она берёт длину буфера?"
Я думал она знает размер сьруктуры.
А вслепую вроде только gets (функция, запрещённая к использованию) пишет.
ещё scanf("%s", &s)
sockaddr_in чтоб кастовать меньше
> if (!~x)
Это что за покемон? Хакерская проверка на -1? Ещё не хватало у знакового числа биты инвертировать...
> && msg.len
Недостижимый код, у тебя CHECK и так вернёт 0. while (msg.len = CHECK(recv(...)), имхо, было бы немного наглядней.
> send(client.sockfd, msg.buf, msg.len, 0);
Уверен, что улетит одним куском? Так можно и байты проебать. Ну и CHECK забыл.
> непроверки результтата байнда
Проверен же. Или я слепой?
Островом сокровищ? Или криптономиконом? Второе, наверное, ближе к теме.
Я всё проверил.
> TCP (STREAM) у нас с recv
прочитал на rsdn что read/write не рекомендуется
> аут оф баунд
это с чего вдрукк?
но он такой маленький няшка, как его не вставить? ^_^
> Ещё не хватало у знакового числа биты инвертировать
а знаковость как на побитловые опереции влияет?
> Недостижимый код
изначально были проверки на -1 без функции, там нужно было, так и осталось.
> улетит одним куском?
на холокосте да, тестовая программка же.
Стандарта под рукой нет, но у меня ощущение, что там возможен UB.
each bit in the result is set if and only if the corresponding bit in the converted operand is
not set). The integer promotions are performed on the operand, and the result has the
promoted type. If the promoted type is an unsigned type, the expression ~E is equivalent
to the maximum value representable in that type minus E.
Обычная побитовая инверсия.
Педанты могут пройтись по упоминаниям sign bit, trap (representation), negative zero и какие там ещё ужасы. Но !~x того не стоит.
А не стоит - без причин добавлять завязку на особенности реализации.
В мане ведь было: "On error, -1 is returned", а не ~0U. И ничего постыдного нет в очевидной проверке x==-1.
https://en.wikipedia.org/wiki/Fast_inverse_square_root#History_and_inv estigation
Медик?
Говно виртуольно-вербозное анально-объектно-ориентированое.