2010-06-17 5 views
4

J'ai couru à travers l'erreur Socket operation on non-socket dans certains de mon code de réseau lors de l'appel connect et passé beaucoup de temps à essayer de comprendre ce qui l'a causé. J'ai finalement compris que la ligne de code suivante causait le problème:Erreur "Socket opération sur socket" en raison de la syntaxe étrange

if ((sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol) < 0)) { 

Voir le problème? Voici ce que la ligne devrait ressembler à:

if ((sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol)) < 0) { 

Ce que je ne comprends pas pourquoi la première ligne incorrecte ne produit pas d'avertissement. Pour mettre une autre manière, ne devrait pas la forme générale:

if (foo = bar() < baz) do_something(); 

paraître étrange au compilateur, en particulier en cours d'exécution avec g++ -Wall -Wextra?

Si ce n'est pas le cas, ne devrait-il pas au moins apparaître comme "mauvais style" à cppcheck, que je suis aussi en train de faire dans le cadre de ma compilation?

+0

Quasiment la raison pour laquelle je * haine * "- conditions" assignation ... – ereOn

+1

Je suis avec vous sur celui-là, ereOn. Je déteste aussi l'opérateur de virgule - une fois j'ai eu par mégarde une virgule à la fin d'une addition répartie sur deux lignes physiques, et il a fallu un certain temps pour comprendre pourquoi je recevais des résultats stupides. Ce serait bien s'il y avait des options #pragmas ou compilateur pour désactiver de tels idiomes de C afin que nous puissions éviter de tels problèmes (et avoir l'erreur/avertissement que l'OP voulait). – JTeagle

+0

@JTeagle: Certainement, oui. En fait, la raison pour laquelle le PO n'a pas reçu d'avertissement était vraiment un manque de chance. Vois ma réponse. – ereOn

Répondre

5

En fait, vous n'obtenez aucun avertissement à cause de la double parenthèse (. Essayez d'enlever une paire, et vous recevrez l'avertissement de retour.

#include <iostream> 

int foo() 
{ 
    return 2; 
} 

int main(int /*argc*/, char** /*argv*/) 
{ 
    int l; 

    if ((l = foo() < 3)) // Won't generate warning under gcc 
    { 
    } 

    if (l = foo() < 3) // will generate a warning "warning: suggest parentheses around assignment used as truth value" 
    { 
    } 

    return EXIT_SUCCESS; 
} 

Pour éviter de telles erreurs/fautes de frappe ennuyeux, je ne pas attribuer une valeur et de le tester dans la même déclaration. C'est trop d'erreur sujette imho.

+0

Pourquoi les parens supplémentaires font-elles une différence? –

+1

@Robert S. Barnes: Je suppose que cela a été fait initialement pour éviter les erreurs comme écrire 'if (i = 5)' au lieu de 'if (i == 5)'. Si vous voulez vraiment faire 'if (i = 5)', le moyen 'gcc' de supprimer cet avertissement est d'entourer l'assignation avec des parenthèses, en le doublant, pour indiquer" ceci n'est pas une faute de frappe, c'est ** signifiait** !". Probablement pas une solution parfaite, comme le montre votre question! – ereOn

+0

Je pense que cppcheck pourrait attraper les deux cas, mais étonnamment, il n'attrape même pas le second cas sans le '()' supplémentaire. –

2

C'est une des raisons pour lesquelles j'essaye de ne pas trop en faire une seule déclaration. Au lieu de

if ((sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol)) < 0) { 

Pourquoi ne pas:

sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol) 
if(sockfd < 0) { 
+0

Exactement. C'est mauvais style de trop mettre dans une déclaration. Aussi, il est aussi beaucoup plus facile de déboguer si vous mettez le si sur la ligne suivante. – humbagumba

+0

Bien que je puisse être d'accord avec la déclaration générale, "Ne pas faire trop dans une déclaration", je ne sais pas que cela s'applique ici. Il y a une valeur pratique à la concision dans le code, et cet idiome C/C++ particulier existe depuis longtemps et est essentiellement une pratique standard. Je programme depuis environ 10 ans et IIRC c'est la première fois que j'ai rencontré ce problème. –

+0

Je suggère que toute valeur pratique acquise par la concision (un peu curieux de savoir à quelle valeur vous pensez) est contrée par une baisse de la lisibilité. Si vous devez faire une pause sur une ligne ou faire une double prise juste pour comprendre exactement quel effet il a, il est probablement préférable de le décomposer. – JTeagle