質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

OpenCV

OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

TCP

TCP(Transmission Control Protocol)とは、トランスポート層のプロトコルで、コネクション型のデータサービスです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

2回答

3698閲覧

ソケット通信のエラー解消(バージョンアップに伴い発生)

Takumi_s

総合スコア13

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

OpenCV

OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

TCP

TCP(Transmission Control Protocol)とは、トランスポート層のプロトコルで、コネクション型のデータサービスです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2019/01/13 14:59

概要

virtual vox上のゲストOSとwindows10間でudp通信をしようと思い,visual studio 2013を用いて以下のプログラムを作成し実行,成功しました.

その後,同じプログラムをvisual studio 2017でリビルドしたところ以下のエラーが発生しており,実行ファイルが作成されません.エラーの原因は何なんでしょうか?

どなたかご教示下されば幸い.よろしくお願いいたします.

エラーメッセージ

重大度レベル コード 説明 プロジェクト ファイル 行 抑制状態 エラー (アクティブ) E0413 "std::_Binder<std::_Unforced, int &, LPSOCKADDR, int>" から "int" への適切な変換関数が存在しません streaming_receiver_win C:\DEVEL_2018\VirtualBox_share\streaming_receiver_win\ver.3\SOURCE\main.cpp 71

ソースコード(関係ありそうなところのみ)

C++

1//サーバー側 2#include <vector> 3#include <fstream> 4 5#include <stdio.h> 6#include <winsock2.h> 7#include <ws2tcpip.h> 8#pragma comment(lib, "wsock32.lib") 9#pragma comment(lib, "ws2_32.lib") 10 11#include <opencv2/opencv.hpp> 12#include <opencv2/highgui/highgui.hpp> 13#include <opencv2/core/core.hpp> 14#include <opencv2/imgproc.hpp> 15#include <opencv2/objdetect.hpp> 16#include <iostream> 17 18#ifdef _DEBUG 19#pragma comment(lib,"C:/SOURCE/OpenCV_3.4.1/BUILD/lib/Debug/opencv_world341d.lib") 20#else 21#pragma comment(lib,"C:/SOURCE/OpenCV_3.4.1/BUILD/lib/Debug/opencv_world341.lib") 22#endif 23 24using namespace std; 25using namespace cv; 26 27/* 省略 */ 28 29int main() { 30 /* ポート番号、ソケット */ 31 int port = 12345; 32 int recvSocket; 33 34 /* sockaddr_in 構造体 */ 35 struct sockaddr_in recvSockAddr; 36 struct sockaddr_in clientSockAddr; 37 38 int clientaddrlen = sizeof(clientSockAddr); 39 /* 各種パラメータ */ 40 int status; 41 int numrcv; 42 unsigned long on = 1; 43 44 /************************************************************/ 45 /* Windows 独自の設定 */ 46 WSADATA data; 47 WSAStartup(MAKEWORD(2, 0), &data); 48 49 /* sockaddr_in 構造体のセット */ 50 memset(&recvSockAddr, 0, sizeof(recvSockAddr)); 51 recvSockAddr.sin_port = htons(port); 52 recvSockAddr.sin_family = AF_INET; 53 recvSockAddr.sin_addr.s_addr = htonl(INADDR_ANY); 54 55 /* ソケット生成 */ 56 recvSocket = socket(AF_INET, SOCK_DGRAM, 0); 57 58 /* バインド(エラー発生箇所) */ 59 status = bind(recvSocket, (LPSOCKADDR)&recvSockAddr, (int) sizeof(recvSockAddr)); 60 61 /* 省略 */ 62 63 /* Windows 独自の設定 */ 64 WSACleanup(); 65} 66

参考サイト

opencv + UDP/IP + Webカメラ

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yohhoy

2019/01/13 15:21

「bind」を「::bind」に変えるとコンパイル通ったりしますか?
Takumi_s

2019/01/13 15:47

ありがとうございます。コンパイルが通り実行できました! 今回の原因は何なのでしょうか?大変恐縮ではございますが,後学のために参考となるサイトなどがあればお教え頂けないでしょうか.
guest

回答2

0

エラーの直接原因、および推奨事項は Chironian さん回答の通りです。

  • WinSockの bind関数 ではなく、C++標準ライブラリの std::bind関数 が意図せず呼び出されている。
  • using namespace std; は利用せずに、std:: のように名前空間を明示指定する方が好ましい。

今回のエラーは、C言語向けAPI(BSD socket互換)を提供する WinSockのレガシーな関数設計 と、C++言語による 関数オーバーロード解決規則 が組み合わさって生じたと考えられます。

WinSockのbind関数は次のプロトタイプ宣言になっています。

cpp

1int bind( 2 SOCKET s, 3 const struct sockaddr *addr, 4 int namelen 5);

一方、C++標準ライブラリのstd::bind関数テンプレートは(およそ)下記のようなプロトタイプ宣言になっています。可変長テンプレートやForwarding Referenceが使われており少々難解ですが、ここでは “どんな実引数も受け付ける関数テンプレート” になっていると解釈ください。この “どんな実引数でも受付ける” 性質が、今回のトラブル要因の一端となります。

cpp

1template <class F, class... BoundArgs> 2ResultType bind(F&& f, BoundArgs&&... bound_args);

説明のため、bind 関数呼出し元コードのエッセンスだけ抽出します。ここでは、実引数に指定する第1引数型(int)および第2引数型(struct sockaddr *)が、WinSock bind 関数プロトタイプ宣言の第1引数型(SOCKET==unsigned __int64)および第2引数型(const struct sockaddr *)とは 厳密一致していない ことに着目してください。

cpp

1// Windows/WinSock標準ヘッダによる型名定義 2typedef unsigned __int64 UINT_PTR; 3typedef UINT_PTR SOCKET; 4typedef struct sockaddr *LPSOCKADDR; 5 6// 呼出しコード 7int recvSocket; 8struct sockaddr_in recvSockAddr; 9 10status = bind(recvSocket, (LPSOCKADDR)&recvSockAddr, (int)sizeof(recvSockAddr)); 11 // 第1引数の型=int 12 // 第2引数の型=struct sockaddr * 13 // 第3引数の型=int

つまり、この関数呼出しには intunsigned __int64 型変換(整数拡張)と、struct sockaddr *const struct sockaddr * 型変換(const付与)が必要となります。通常であればこれらの型変換は暗黙に行われるため、プログラマが意識する必要はありません。WinSockはC言語時代に設計された古風なAPI仕様ですから、このコードのような型キャストは自然に行われるものと思います。

一方、C++標準ライブラリ std::bind 関数テンプレートでは実引数から全てのパラメータ型を推論するため、第1引数型F==int, 第2引数型以降BoundArgs=={struct sockaddr *, int}と推論されます[※]。つまり、全ての実引数型に関数パラメータ型が完全一致する関数が(意図せず)生み出されます。

ソースコード中で using namesapce std; を行った場合、この std::bind 関数テンプレートが、元々グローバル名前空間にあるWinSockの bind 関数と同列に並びます。C++言語の関数オーバーロード解決規則は非常に複雑ですが、ここでは「型変換が必要となる候補:WinSock bind関数」と「型変換が不要な候補:C++標準ライブラリstd::bind 型推論結果」が天秤にかけられた結果、プログラマの意図しない後者が選択されています。

※注:厳密にはForwarding Referenceのため、テンプレートパラメータF==int&、第1引数型はint&に型推論されます。また可変テンプレートパラメータBoundArgs=={struct sockaddr *, int}となり、第2,3引数型はそれぞれstruct sockaddr *&&, int&&に型推論されます。


おまけ: 実は質問のケースでは、下記コードのようにプロトタイプ宣言型と実引数の型を厳密一致させると、期待通りWinSockの bind が呼び出されるようになります。しかし、この解決方法はあまりにC++言語の難解なルールに依存しているため、素直に名前空間を分けて扱うことをおススメします。

cpp

1// OK: 明示的なキャストにより全ての引数型を厳密一致させる 2status = bind((SOCKET) recvSocket, 3 (const struct sockaddr *) &recvSockAddr, 4 (int) sizeof(recvSockAddr));

Demo: https://www.godbolt.ms/z/NiUAlN

投稿2019/01/15 07:42

編集2019/01/15 08:39
yohhoy

総合スコア6191

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Takumi_s

2019/01/15 09:36

非常に丁寧な解説感謝いたします. 今回この事態が発生した要因に,私の不勉強による雑なコーディングがあったと思います. 今すぐに言語に精通できるわけでは決してありませんが,出来る限り意識してコーディングしていきたいと思います. 重ね重ね,ご丁寧な解説ありがとうございました.
guest

0

ベストアンサー

こんにちは。

C++11でstd::bindが追加されています。VC++ 2013はC++11にはほとんど対応していませんが、VC++ 2017はほぼ対応しています。
結果、std::bindの方とマッチしたのだろうと思います。

using namespace std;を止めて、1つ1つ std:: を付けた方が良いと思います。


C++は多量にキーを押すことでコンパイラにより多くのバグを検出させる言語と割り切るのも一つかも。
(キーをケチりすぎるとろくなことになりません。)

投稿2019/01/13 15:30

Chironian

総合スコア23272

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Takumi_s

2019/01/13 15:49

回答ありがとうございます. そういう考え方もあるのですね.大変勉強になりました.
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問