Сбой C Socket на устройстве iPhone. EXC_BAD_ACCESS

У меня есть код, который хорошо работает на симуляторе, но как только я пробую его на устройстве, программа падает.

Это происходит при инициализации сокета. Вот мой код и то, что выдает запуск/отладка. (ИМЯ_СЕРВЕРА — это имя хоста моей машины, на которой работает сервер)

Ошибка:

Program received signal:  “EXC_BAD_ACCESS”.
warning: Unable to read symbols for /Developer/Platforms/iPhoneOS.platform/DeviceSupport/4.3.3 (8J3)/Symbols/Developer/usr/lib/libXcodeDebuggerSupport.dylib (file not found).

in .h

    int connectionSocket;
struct hostent *server;
struct sockaddr_in server_addr;

in .m

- (void)viewDidLoad {
[super viewDidLoad];

TRANSFER_COMPLETED = false;
TIME_COMPLETED = false;

//[UIApplication sharedApplication].idleTimerDisabled = YES;    //Disable app sleep (check this out)


//Build connection to Server
portNumber = PORT_NUM;
connectionSocket = socket(PF_INET, SOCK_STREAM, 0); 
server = gethostbyname(SERVER_NAME);
server_addr.sin_family = AF_INET;     
server_addr.sin_port = htons(portNumber);   
//server_addr.sin_addr = *((struct in_addr *)server->h_addr);   
memcpy ( &( server_addr.sin_addr ), server->h_addr, server->h_length );

if (connect(connectionSocket, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1) 
{
    perror("Connect");
    exit(1);
}   

//Setup Battery monitoring and Device characteristics
myDevice = [UIDevice currentDevice];
myDevice.batteryMonitoringEnabled = YES;
NSString* sysName = myDevice.systemName;
NSString* sysVersion = myDevice.systemVersion;

//Name the file for this device

NSString* myString = [NSString stringWithFormat:@"systemName:%@ systemVersion:%@ \n", sysName, sysVersion];

const char* deviceInfo = malloc(128);
char* deviceSettings = malloc(256);

deviceInfo = [myString UTF8String];

//Get the battery State
int intBatteryState = myDevice.batteryState;
char* batteryState = malloc(24);
switch(intBatteryState){
    case 0: 
        batteryState = "Unknown";
        break;
    case 1:
        batteryState = "Unplugged";
        break;
    case 2:
        batteryState = "Charging";
        break;
    case 3:
        batteryState = "plugged and full";
        break;
    default:
        batteryState = "Error";
        break;
}   

sprintf(deviceSettings, "iOS Test *** APPLICATION_BUFFER_SIZE(B): %i, SLEEP_TIME(microseconds) per app buffer size: %i, TOTAL_BYTES_EXPECTED per download: %i, TOTAL_DOWNLOADS: %i, TEST_TIME(s): %i, Battery State:%s \n", (int) round(APPLICAION_BUFFER_SIZE), SLEEP_TIME, TOTAL_BYTES_EXPECTED, TOTAL_DOWNLOADS, TEST_TIME, batteryState);

send(connectionSocket, DEVICE_NAME, strlen(DEVICE_NAME), 0);
sleep(1);
send(connectionSocket, deviceSettings, strlen(deviceSettings), 0);
send(connectionSocket, deviceInfo, strlen(deviceInfo), 0);

free(deviceSettings);
//free(deviceInfo);//Says it is being freed without being allocated but I allocated it with malloc...
//free(batteryState); 

//  [NSThread detachNewThreadSelector:@selector(download) toTarget:self withObject:nil];

// [NSThread detachNewThreadSelector:@selector(keepRunning) toTarget:self withObject:nil]; // [NSThread detachNewThreadSelector:@selector(busyLoop) toTarget:self withObject:nil]; //

//  [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(batteryLevelDidChange) name:UIDeviceBatteryLevelDidChangeNotification object:nil];

// [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(batteryStateDidChange) name:UIDeviceBatteryStateDidChangeNotification object:nil];


person Michael    schedule 20.05.2011    source источник
comment
Просто предложение: server = gethostbyname(SERVER_NAME); устарело. Приятно посмотреть на getaddrinfo()   -  person Mayank    schedule 20.05.2011
comment
Каков результат server = gethostbyname(SERVER_NAME);   -  person Mayank    schedule 20.05.2011


Ответы (1)


Попробуйте использовать

memcpy ( &( serv_addr.sin_addr ), server->h_addr, server->h_length );

на месте

server_addr.sin_addr = *((struct in_addr *)server->h_addr);  

ИЛИ вы можете использовать server_addr.sin_addr.s_addr = inet_addr(IP);

Это только для того, чтобы избежать аварии. Но я не уверен, почему server_addr.sin_addr = *((struct in_addr *)server->h_addr); вылетит.

РЕДАКТИРОВАТЬ: Попробуйте это:

portNumber = PORT_NUM;
connectionSocket = socket(AF_INET, SOCK_STREAM, 0); 
server_addr.sin_family = AF_INET;     
server_addr.sin_port = htons(portNumber);   
server_addr.sin_addr.saddr = htonl(INADDR_ANY);

Для этого не требуется server = gethostbyname(SERVER_NAME);

Еще одна вещь, которую я отметил:

connectionSocket = socket(**PF_INET**, SOCK_STREAM, 0); 
//server = gethostbyname(SERVER_NAME);
server_addr.sin_family = **AF_INET**;  

Это нормально? Я имею в виду разные протоколы в двух утверждениях?

person Mayank    schedule 20.05.2011
comment
@Mayank спасибо за предложение, к сожалению, оно ничего не изменило. - person Michael; 20.05.2011
comment
@Michael: Я понимаю, что оба утверждения похожи ... Не могли бы вы добавить еще немного кода ... Например, если вы проверяете NULL, прежде чем войти внутрь. - person Mayank; 20.05.2011
comment
Однажды я сделал подобную ошибку. В этом случае я проверял if (NULL == server), но сервер был неинициализирован, а не NULL. надеюсь такие вещи уже решаются - person Mayank; 20.05.2011
comment
Хм, если честно, я копаюсь в C через несколько лет, поэтому я могу пропустить некоторые важные шаги... Я обновил код, чтобы включить всю функцию viewdidload из .m, и я закомментировал все вызовы к другим локальным функции, чтобы убедиться, что проблема именно в этом блоке кода. Когда я сказал, что ваше предложение ничего не изменило, я имел в виду, что программа работала так же... не ваш код был таким же - я не имел в виду, что это могло произойти таким образом. - person Michael; 20.05.2011
comment
@Майкл: Это нормально. Даже в сокеты С давно не заглядывал. Что ж, нам нужно выяснить, что здесь происходит. Не могли бы вы проверить вывод server = gethostbyname(SERVER_NAME); - person Mayank; 20.05.2011
comment
@Mayank, похоже, ты что-то понял. (сервер == NULL) верно. Это должно означать, что мне нужно использовать malloc, а не просто объявлять его в заголовке? - person Michael; 20.05.2011
comment
Нет, если вывод server = gethostbyname(SERVER_NAME); равен NULL, это означает, что библиотека C не понимает SERVER_NAME. Если бы это было в IP-сети, я мог бы попросить вас проверить IP-адрес системы. Я не знаю, предоставляет ли iPhone IP - person Mayank; 20.05.2011
comment
Возиться с sin_addr и тому подобное всегда неправильно. Вы никогда не должны сами создавать структуры sockaddr_* или использовать gethostbyname. Всегда используйте только getaddrinfo и getnameinfo. - person R.. GitHub STOP HELPING ICE; 20.05.2011
comment
Просто предложение: server = gethostbyname(SERVER_NAME); устарел. Приятно посмотреть на getaddrinfo() - person Mayank; 20.05.2011
comment
@Mayank, это нехорошо ... Странно, как это будет работать на симуляторе, но не на устройстве. - person Michael; 20.05.2011
comment
@Mayank @R.. спасибо за подсказку, я посмотрю, что такое getaddrinfo(). - person Michael; 20.05.2011
comment
@Michael: понятия не имею, так как никогда не работал с мобильными устройствами. Но это довольно интересный случай, и его можно задать как новый вопрос в SO, как только эта проблема будет решена. Хорошо, если подходы SERVER_NAME и IP не работают, последняя попытка может быть server_addr.sin_addr.saddr = htonl(INADDR_ANY);. Если это сработает, протестируйте свой бизнес-кейс. Как только все будет в порядке, измените свой код, чтобы включить getaddrinfo, как это было предложено @R. - person Mayank; 20.05.2011
comment
@Mayank Хорошо, мне еще не повезло, но я в основном использую код из предложенной вами ссылки, но ему не нравится мое имя узла, оно говорит getaddrinfo: имя узла или имя сервера указано или неизвестно, я пробовал свой IP и мое имя хоста в имени узла, и у меня есть имя сервера как 11313, мне нужно будет продолжать копаться в нем. - person Michael; 20.05.2011
comment
Странно... 11313 - это тоже ваш номер порта :-) - person Mayank; 20.05.2011
comment
@Mayank Я думаю, так это и должно работать. с IP в имени сервера. На данный момент я в основном просто пытаюсь что-то взломать :). Все, что работает, было бы потрясающе. - person Michael; 20.05.2011
comment
Вы пробовали server_addr.sin_addr.saddr = htonl(INADDR_ANY); Попробуйте один раз, когда найдете время :-) - person Mayank; 20.05.2011
comment
Да, я обязательно попробовал все ваши идеи. gethostbyname() по-прежнему выводит NULL, поэтому мне нужно сначала решить эту проблему. - person Michael; 20.05.2011
comment
Кстати, я ценю всю вашу помощь ... Я пытался поднять ваш пост, но, думаю, моя репутация слишком низкая. - person Michael; 20.05.2011
comment
Шаг в правильном направлении. Программа больше не падает, но сокет не связывается с сервером. - person Michael; 20.05.2011
comment
Может ли он подключиться... Посмотрите здесь, может помочь списки. apple.com/archives/darwin-development/2002/May/ - person Mayank; 20.05.2011